Commit b9945754 authored by Florian Blasius's avatar Florian Blasius 🤘

[api update] many layout fixes.

Add methods for default widget properties.
parent 1b97be57
use orbtk::*;
use std::{cell::Cell, rc::Rc};
// #[derive(Default)]
// struct MainViewState {
// counter: Cell<i32>,
......@@ -126,6 +124,25 @@ use std::{cell::Cell, rc::Rc};
// }
// }
widget!(MainView);
impl Template for MainView {
fn template(self, _: Entity, context: &mut BuildContext) -> Self {
self.name("MainView").child(
Container::create()
.background("#6195ED")
.vertical_alignment("Start")
.child(
TextBlock::create()
.text("TextBlock")
.font_size(38.0)
.build(context),
)
.build(context),
)
}
}
fn main() {
let mut application = Application::default();
......@@ -134,6 +151,6 @@ fn main() {
.bounds((100.0, 100.0, 420.0, 730.0))
.title("OrbTk - widgets example")
.debug_flag(true)
.build(TextBlock::create().text("TextBlock").font_size(38.0));
.build(MainView::create());
application.run();
}
......@@ -127,7 +127,7 @@ impl Layout for PaddingLayout {
margin.left(),
margin.right()
),
vertical_alignment.align_position(
vertical_alignment.align_measure(
parent_size.1,
self.desired_size.borrow().height(),
margin.top(),
......@@ -158,7 +158,7 @@ impl Layout for PaddingLayout {
if let Ok(child_bounds) = ecm.borrow_mut_component::<Bounds>(*child) {
child_bounds.set_x(
padding.left()
+ child_horizontal_alignment.align_measure(
+ child_horizontal_alignment.align_position(
available_size.0,
child_bounds.width(),
child_margin.left(),
......
......@@ -12,7 +12,7 @@ macro_rules! property {
impl $property {
/// Returns the value of a property.
pub fn get(entity: Entity, ecm: &EntityComponentManager) -> $type {
get_property::<$type>(entity, ecm)
get_property::<$property>(entity, ecm).0
}
}
......@@ -20,13 +20,13 @@ macro_rules! property {
fn from(property: $property) -> $type {
property.0.into()
}
}
}
impl From<$type> for $property {
fn from(value: $type) -> $property {
$property(value)
}
}
}
impl Into<PropertySource<$property>> for $type {
fn into(self) -> PropertySource<$property> {
......@@ -43,14 +43,15 @@ macro_rules! property {
}
/// Used to define a widget, with properties and event handlers.
#[macro_export]
macro_rules! widget {
( $(#[$widget_doc:meta])* $widget:ident $(<$state:ident>)* $(: $( $handler:ident ),*)* { $($(#[$prop_doc:meta])* $property:ident: $property_type:tt ),* } ) => {
( $(#[$widget_doc:meta])* $widget:ident $(<$state:ident>)* $(: $( $handler:ident ),*)* $( { $($(#[$prop_doc:meta])* $property:ident: $property_type:tt ),* } )* ) => {
use std::{ any::TypeId, rc::Rc, collections::HashMap};
use dces::prelude::{Component, ComponentBox, SharedComponentBox };
use crate::{event::EventHandler,
properties::{Bounds, Constraint, VerticalAlignment, HorizontalAlignment, Visibility},
use crate::{event::EventHandler,
properties::{Bounds, Constraint, VerticalAlignment, HorizontalAlignment, Visibility, Name},
widget::{PropertySource, Widget, BuildContext}};
$(#[$widget_doc])*
......@@ -60,17 +61,20 @@ macro_rules! widget {
event_handlers: Vec<Rc<dyn EventHandler>>,
bounds: Bounds,
constraint: Constraint,
name: Option<Name>,
horizontal_alignment: HorizontalAlignment,
vertical_alignment: VerticalAlignment,
visibility: Visibility,
$(
$property: Option<PropertySource<$property_type>>,
)*
$(
$(
$property: Option<PropertySource<$property_type>>,
)*
)*
children: Vec<Entity>,
}
impl $widget {
/// Sets an attached property or shares it by the given id.
/// Sets or shares an attached property.
pub fn attach<P: Component>(mut self, property: impl Into<PropertySource<P>>) -> Self {
match property.into() {
PropertySource::Value(value) => {
......@@ -82,16 +86,42 @@ macro_rules! widget {
}
self
}
/// Sets or shares the vertical alignment property.
pub fn vertical_alignment<P: Into<PropertySource<VerticalAlignment>>>(self, vertical_alignment: P) -> Self {
self.attach(vertical_alignment)
}
/// Sets or shares the horizontal alignment property.
pub fn horizontal_alignment<P: Into<PropertySource<VerticalAlignment>>>(self, horizontal_alignment: P) -> Self {
self.attach(horizontal_alignment)
}
/// Sets or shares the visibility property.
pub fn visibility<P: Into<PropertySource<Visibility>>>(self, visibility: P) -> Self {
self.attach(visibility)
}
// todo: constraint also by with min max, ...
/// Sets the debug name of the widget.
pub fn name<P: Into<Name>>(mut self, name: P) -> Self {
self.name = Some(name.into());
self
}
$(
$(#[$prop_doc])*
pub fn $property<P: Into<PropertySource<$property_type>>>(mut self, $property: P) -> Self {
if !self.$property.is_none() {
return self;
}
$(
$(#[$prop_doc])*
pub fn $property<P: Into<PropertySource<$property_type>>>(mut self, $property: P) -> Self {
if !self.$property.is_none() {
return self;
}
self.$property = Some($property.into());
self
}
self.$property = Some($property.into());
self
}
)*
)*
}
......@@ -109,11 +139,14 @@ macro_rules! widget {
event_handlers: vec![],
bounds: Bounds::default(),
constraint: Constraint::default(),
name: None,
horizontal_alignment: HorizontalAlignment::default(),
vertical_alignment: VerticalAlignment::default(),
visibility: Visibility::default(),
$(
$property: None,
$(
$property: None,
)*
)*
children: vec![],
}
......@@ -138,7 +171,7 @@ macro_rules! widget {
fn build(self, context: &mut BuildContext) -> Entity {
let entity = context.create_entity();
let this = self.template(entity, context);
let this = self.template(entity, context);
if let Some(render_object) = this.render_object() {
context.register_render_object(entity, render_object);
......@@ -152,7 +185,7 @@ macro_rules! widget {
context.register_property(entity, this.vertical_alignment);
context.register_property(entity, this.horizontal_alignment);
context.register_property(entity, this.visibility);
// register attached properties
for (_, property) in this.attached_properties {
context.register_property_box(entity, property);
......@@ -162,22 +195,28 @@ macro_rules! widget {
context.register_property_shared_box(entity, property);
}
// register properties
$(
if let Some($property) = this.$property {
match $property {
PropertySource::Value(value) => {
context.register_property(entity, value);
},
PropertySource::Source(source) => {
context.register_shared_property::<$property_type>(entity, source);
$(
if let Some($property) = this.$property {
match $property {
PropertySource::Value(value) => {
context.register_property(entity, value);
},
PropertySource::Source(source) => {
context.register_shared_property::<$property_type>(entity, source);
}
}
}
}
)*
)*
)*
// register name
if let Some(name) = this.name {
println!("{} (id = {}, children_len = {})", name.0, entity, this.children.len());
context.register_property(entity, name);
}
for child in this.children {
context.append_child(entity, child);
}
......@@ -186,4 +225,4 @@ macro_rules! widget {
}
}
};
}
\ No newline at end of file
}
use std::f64;
/// `BoxConstraint` describes a box constraint.
#[derive(Copy, Clone, Default, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct BoxConstraint {
width: f64,
height: f64,
......@@ -9,6 +11,19 @@ pub struct BoxConstraint {
max_height: f64,
}
impl Default for BoxConstraint {
fn default() -> Self {
BoxConstraint {
width: 0.0,
height: 0.0,
min_width: 0.0,
min_height: 0.0,
max_width: f64::MAX,
max_height: f64::MAX,
}
}
}
property!(
/// `Constraint` describes the box constraint (min, max size) of a widget.
Constraint(BoxConstraint)
......@@ -67,7 +82,7 @@ impl ConstraintExtension for BoxConstraint {
self.width = width;
}
fn height(&self) -> f64 {
fn height(&self) -> f64 {
self.height
}
......@@ -75,7 +90,7 @@ impl ConstraintExtension for BoxConstraint {
self.height = height;
}
fn min_width(&self) -> f64 {
fn min_width(&self) -> f64 {
self.min_width
}
......@@ -83,7 +98,7 @@ impl ConstraintExtension for BoxConstraint {
self.min_width = min_width;
}
fn min_height(&self) -> f64 {
fn min_height(&self) -> f64 {
self.min_height
}
......@@ -91,7 +106,7 @@ impl ConstraintExtension for BoxConstraint {
self.min_height = min_height;
}
fn max_width(&self) -> f64 {
fn max_width(&self) -> f64 {
self.max_width
}
......@@ -99,7 +114,7 @@ impl ConstraintExtension for BoxConstraint {
self.max_width = max_width;
}
fn max_height(&self) -> f64 {
fn max_height(&self) -> f64 {
self.max_height
}
......@@ -127,7 +142,7 @@ impl ConstraintExtension for BoxConstraint {
}
impl ConstraintExtension for Constraint {
fn width(&self) -> f64 {
fn width(&self) -> f64 {
self.0.width
}
......@@ -135,7 +150,7 @@ impl ConstraintExtension for Constraint {
self.0.width = width;
}
fn height(&self) -> f64 {
fn height(&self) -> f64 {
self.0.height
}
......@@ -143,7 +158,7 @@ impl ConstraintExtension for Constraint {
self.0.height = height;
}
fn min_width(&self) -> f64 {
fn min_width(&self) -> f64 {
self.0.min_width
}
......@@ -151,7 +166,7 @@ impl ConstraintExtension for Constraint {
self.0.min_width = min_width;
}
fn min_height(&self) -> f64 {
fn min_height(&self) -> f64 {
self.0.min_height
}
......@@ -159,7 +174,7 @@ impl ConstraintExtension for Constraint {
self.0.min_height = min_height;
}
fn max_width(&self) -> f64 {
fn max_width(&self) -> f64 {
self.0.max_width
}
......@@ -167,7 +182,7 @@ impl ConstraintExtension for Constraint {
self.0.max_width = max_width;
}
fn max_height(&self) -> f64 {
fn max_height(&self) -> f64 {
self.0.max_height
}
......@@ -176,7 +191,7 @@ impl ConstraintExtension for Constraint {
}
fn perform(&self, size: (f64, f64)) -> (f64, f64) {
self.0.perform(size)
self.0.perform(size)
}
}
......@@ -191,4 +206,4 @@ fn constrain(val: f64, min: f64, max: f64, size: f64) -> f64 {
} else {
val
}
}
\ No newline at end of file
}
// use crate::structs::{Brush, Color};
use crate::
structs::{Brush, Color};
// /// Used to draw the border brush of a widget.
// #[derive(Clone)]
// pub struct BorderBrush(pub Brush);
property!(
/// `BorderBrush` describes the border brush.
BorderBrush(Brush)
);
// property!(
// BorderBrush,
// BorderBrushProperty,
// border_brush,
// border_brush_prop
// );
// --- Conversions ---
// impl From<BorderBrush> for Color {
// fn from(b: BorderBrush) -> Color {
// b.0.into()
// }
// }
impl From<&str> for BorderBrush {
fn from(s: &str) -> BorderBrush {
BorderBrush(s.into())
}
}
// impl Default for BorderBrush {
// fn default() -> BorderBrush {
// "#000000".into()
// }
// }
impl Into<PropertySource<BorderBrush>> for &str {
fn into(self) -> PropertySource<BorderBrush> {
PropertySource::Value(BorderBrush::from(self))
}
}
// impl From<&str> for BorderBrush {
// fn from(s: &str) -> BorderBrush {
// BorderBrush(s.into())
// }
// }
impl From<BorderBrush> for Color {
fn from(b: BorderBrush) -> Color {
b.0.into()
}
}
// /// Represents the degree to which the corners of a Border are rounded.
// #[derive(Default, Clone, Copy)]
// pub struct BorderRadius(pub f64);
// property!(
// BorderRadius,
// BorderRadiusProperty,
// border_radius,
// border_radius_prop
// );
// impl From<f64> for BorderRadius {
// fn from(t: f64) -> Self {
// BorderRadius(t)
// }
// }
property!(
/// `IconSize` describes the degree to which the corners of a Border are rounded.
BorderRadius(f64)
);
// use crate::structs::{Spacer, Thickness};
// /// Represents relative thickness of a Border.
// #[derive(Default, Clone, Copy)]
// pub struct BorderThickness(pub Thickness);
// property!(
// BorderThickness,
// BorderThicknessProperty,
// border_thickness,
// border_thickness_prop
// );
// impl Spacer for BorderThickness {
// fn left(&self) -> f64 {
// self.0.left
// }
// fn set_left(&mut self, left: f64) {
// self.0.left = left;
// }
// fn top(&self) -> f64 {
// self.0.top
// }
// fn set_top(&mut self, top: f64) {
// self.0.top = top;
// }
// fn right(&self) -> f64 {
// self.0.right
// }
// fn set_right(&mut self, right: f64) {
// self.0.right = right;
// }
// fn bottom(&self) -> f64 {
// self.0.bottom
// }
// fn set_bottom(&mut self, bottom: f64) {
// self.0.bottom = bottom;
// }
// fn thickness(&self) -> Thickness {
// self.0
// }
// fn set_thickness<T: Into<Thickness>>(&mut self, thickness: T) {
// self.0 = thickness.into();
// }
// }
// impl From<(f64, f64, f64, f64)> for BorderThickness {
// fn from(t: (f64, f64, f64, f64)) -> Self {
// BorderThickness(Thickness::new(t.0, t.1, t.2, t.3))
// }
// }
// impl From<(f64, f64)> for BorderThickness {
// fn from(t: (f64, f64)) -> Self {
// BorderThickness(Thickness::new(t.0, t.1, t.0, t.1))
// }
// }
// impl From<f64> for BorderThickness {
// fn from(t: f64) -> Self {
// BorderThickness(Thickness::new(t, t, t, t))
// }
// }
use crate::structs::{Spacer, Thickness};
property!(
/// `BorderThickness` describes the relative thickness of a border.
BorderThickness(Thickness)
);
// --- Trait implementations ---
impl Spacer for BorderThickness {
fn left(&self) -> f64 {
self.0.left
}
fn set_left(&mut self, left: f64) {
self.0.left = left;
}
fn top(&self) -> f64 {
self.0.top
}
fn set_top(&mut self, top: f64) {
self.0.top = top;
}
fn right(&self) -> f64 {
self.0.right
}
fn set_right(&mut self, right: f64) {
self.0.right = right;
}
fn bottom(&self) -> f64 {
self.0.bottom
}
fn set_bottom(&mut self, bottom: f64) {
self.0.bottom = bottom;
}
fn thickness(&self) -> Thickness {
self.0
}
fn set_thickness<T: Into<Thickness>>(&mut self, thickness: T) {
self.0 = thickness.into();
}
}
// --- Conversions ---
impl From<(f64, f64, f64, f64)> for BorderThickness {
fn from(t: (f64, f64, f64, f64)) -> Self {
BorderThickness::from(Thickness::new(t.0, t.1, t.2, t.3))
}
}
impl Into<PropertySource<BorderThickness>> for (f64, f64, f64, f64) {
fn into(self) -> PropertySource<BorderThickness> {
PropertySource::Value(BorderThickness::from(self))
}
}
impl From<(f64, f64)> for BorderThickness {
fn from(t: (f64, f64)) -> Self {
BorderThickness::from(Thickness::new(t.0, t.1, t.0, t.1))
}
}
impl Into<PropertySource<BorderThickness>> for (f64, f64) {
fn into(self) -> PropertySource<BorderThickness> {
PropertySource::Value(BorderThickness::from(self))
}
}
impl From<f64> for BorderThickness {
fn from(t: f64) -> Self {
BorderThickness::from(Thickness::new(t, t, t, t))
}
}
impl Into<PropertySource<BorderThickness>> for f64 {
fn into(self) -> PropertySource<BorderThickness> {
PropertySource::Value(BorderThickness::from(self))
}
}
......@@ -3,12 +3,14 @@
pub use self::font_icon::*;
pub use self::image::*;
pub use self::text::*;
pub use self::name::*;
pub use self::text_selection::*;
pub use self::water_mark::*;
mod font_icon;
mod image;
mod text;
mod name;
mod text_selection;
mod water_mark;
......
property!(
/// `Name` is use for debugging purposes.
Name(String)
);
// --- Conversions ---
impl From<&str> for Name {
fn from(s: &str) -> Name {
Name(s.into())
}
}
impl Into<PropertySource<Name>> for &str {
fn into(self) -> PropertySource<Name> {
PropertySource::Value(Name::from(self))
}
}
\ No newline at end of file
This diff is collapsed.
// use dces::prelude::Entity;
// use crate::{
// layout::PaddingLayout,
// properties::*,
// render_object::RectangleRenderObject,
// widget::{Template, Widget, Template, BuildContext, Template},
// };
// widget!(
// /// The `Container` represents a layout that surrounds its child with a padding. Draws a box around the child.
// Container
// (
// BackgroundProperty,
// BorderRadiusProperty,
// BorderThicknessProperty,
// BorderBrushProperty,
// PaddingProperty
// )
// );
// impl Widget for Container {
// fn create() -> Self {
// Container::new()
// .padding(0.0)
// .background("transparent")
// .border_radius(0.0)
// .border_thickness(0.0)
// .border_brush("transparent")
// .render_object(RectangleRenderObject)
// .layout(PaddingLayout::new())
// .debug_name("Container")
// }
// }
use dces::prelude::Entity;
use crate::{
widget::Template,
properties::*,
};
use crate::{properties::*, widget::Template, render_object::{RenderObject, RectangleRenderObject}, layout::{Layout, PaddingLayout}};
widget!(///This is a container
Container {
/// Sets the background
background: Background
});
widget!(
/// The `Container` layout widget surrounds its child with a padding. Draws a box around the child.
Container {
/// Sets or shares the background property.
background: Background,
/// Sets or shares the border radius property.
border_radius: BorderRadius,
/// Sets or shares the border thickness property.
border_thickness: BorderThickness,
/// Sets or shares the border brush property.
border_brush: BorderBrush,
/// Sets or shares the padding property.
padding: Padding
}
);
impl Template for Container {
fn template(self, id: Entity, context: &mut BuildContext) -> Self {
self
// Template::new(id)
fn template(self, _: Entity, _: &mut BuildContext) -> Self {
self.name("Container").padding(0.0)
.background("transparent")
.border_radius(0.0