Commit 92ee935e authored by Florian Blasius's avatar Florian Blasius 🤘

[api update] textbox (wip), light theme example.

widget container propert api.
parent 4991f595
This diff is collapsed.
use orbtk::*;
// #[derive(Default)]
// struct MainViewState {
// counter: Cell<i32>,
// }
// impl MainViewState {
// pub fn increment(&self) {
// self.counter.set(self.counter.get() + 1)
// }
// }
// impl State for MainViewState {
// fn update(&self, context: &mut Context<'_>) {
// if let Ok(button_count_text) = context.widget().borrow_mut_property::<Text>() {
// button_count_text.0 = format!("Button count: {}", self.counter.get());
// }
// }
// }
use std::cell::Cell;
use orbtk::*;
// widget!(MainView);
#[derive(Default)]
pub struct MainViewState {
counter: Cell<i32>,
}
// impl Widget for MainView {
// fn create() -> Self {
// let state = Rc::new(MainViewState::default());
// let button_count_text = Property::new(Text::from("Button count: 0"));
impl MainViewState {
fn increment(&self) {
self.counter.set(self.counter.get() + 1)
}
}
// MainView::new()
// .state(state.clone())
// .child(
// Grid::create()
// .margin(8.0)
// .columns(
// Columns::create()
// .column("Auto")
// .column(32.0)
// .column("Auto")
// .column("*")
// .build(),
// )
// .rows(
// Rows::create()
// .row("Auto")
// .row("Auto")
// .row("Auto")
// .row("Auto")
// .row("Auto")
// .row("Auto")
// .build(),
// )
// // Column 0
// .child(create_header("Button", 0, 0))
// .child(
// Button::create()
// .text("Button")
// .margin((0.0, 8.0, 0.0, 0.0))
// .font_icon(material_font_icons::CHECK_FONT_ICON)
// .attach(GridColumn(0))
// .attach(GridRow(1))
// .on_click(move |_| {
// state.increment();
// true
// }),
// )
// .child(
// Button::create()
// .text("Primary")
// .selector(Selector::from("button").class("primary"))
// .margin((0.0, 8.0, 0.0, 0.0))
// .font_icon(material_font_icons::CHECK_FONT_ICON)
// .attach(GridColumn(0))
// .attach(GridRow(2)),
// )
// .child(
// ToggleButton::create()
// .text("ToggleButton")
// .margin((0.0, 8.0, 0.0, 0.0))
// .attach(GridColumn(0))
// .attach(GridRow(3)),
// )
// .child(
// CheckBox::create()
// .text("CheckBox")
// .margin((0.0, 8.0, 0.0, 0.0))
// .attach(GridColumn(0))
// .attach(GridRow(4)),
// )
// .child(
// Switch::create()
// .margin((0.0, 8.0, 0.0, 0.0))
// .attach(GridColumn(0))
// .attach(GridRow(5)),
// )
// // Column 2
// .child(create_header("Text", 2, 0))
// .child(
// TextBlock::create()
// .selector(Selector::new().class("body"))
// .text_prop(button_count_text.share())
// .margin((0.0, 8.0, 0.0, 0.0))
// .attach(GridColumn(2))
// .attach(GridRow(1)),
// )
// .child(
// TextBox::create()
// .water_mark("TextBox...")
// .margin((0.0, 8.0, 0.0, 0.0))
// .attach(GridColumn(2))
// .attach(GridRow(2)),
// ),
// )
// .attach(button_count_text)
// .debug_name("MainView")
// }
// }
impl State for MainViewState {
fn update(&self, context: &mut Context<'_>) {
if let Ok(button_count_text) = context.widget().borrow_mut::<Text>() {
button_count_text.0 = format!("Button count: {}", self.counter.get());
}
}
}
fn create_header(context: &mut BuildContext, text: &str, grid: usize, column: usize) -> Entity {
TextBlock::create()
......@@ -125,11 +30,17 @@ fn create_header(context: &mut BuildContext, text: &str, grid: usize, column: us
.build(context)
}
widget!(MainView);
widget!(
MainView<MainViewState> {
count_text: Text
}
);
impl Template for MainView {
fn template(self, _: Entity, context: &mut BuildContext) -> Self {
self.name("MainView").child(
fn template(self, id: Entity, context: &mut BuildContext) -> Self {
let state = self.clone_state();
self.name("MainView").count_text("Button count: 0").child(
Grid::create()
.margin(8.0)
.columns(
......@@ -160,8 +71,7 @@ impl Template for MainView {
.attach(GridColumn(0))
.attach(GridRow(1))
.on_click(move |_| {
println!("Blub");
// state.increment();
state.increment();
true
}).build(context)
)
......@@ -199,7 +109,7 @@ impl Template for MainView {
.child(
TextBlock::create()
.selector(SelectorValue::new().class("body"))
// .text(button_count_text.share())
.text(id)
.margin((0.0, 8.0, 0.0, 0.0))
.attach(GridColumn(2))
.attach(GridRow(1)).build(context)
......@@ -207,6 +117,7 @@ impl Template for MainView {
.child(
TextBox::create()
.placeholder("TextBox...")
.text("")
.margin((0.0, 8.0, 0.0, 0.0))
.attach(GridColumn(2))
.attach(GridRow(2)).build(context)
......
......@@ -3,9 +3,9 @@ use std::collections::HashMap;
use dces::prelude::Entity;
#[derive(Default)]
/// The `Global` struct is used to define global `properties` that could be accsed application width.
/// The `Global` struct is used to define global `properties` that could be access application width.
pub struct Global {
/// Contains the current focues widget.
/// Contains the current focused widget.
pub focused_widget: Option<Entity>,
/// Used to reference widgets by its css id.
......
......@@ -13,7 +13,7 @@ use crate::{
layout::Layout,
properties::*,
render_object::RenderObject,
structs::{Size, Rect},
structs::{Size, Rect, Point},
systems::{
EventSystem, InitSystem, LayoutSystem, PostLayoutStateSystem, RenderSystem, StateSystem,
},
......@@ -98,6 +98,7 @@ impl<'a> WindowBuilder<'a> {
.create_entity()
.with(Global::default())
.with(Name::from("Window"))
.with(Point::default())
.with(Bounds::from(Rect::new(
0.0,
0.0,
......
......@@ -2,26 +2,25 @@ use std::rc::Rc;
use crate::{
event::{Event, EventBox, EventHandler},
properties::{Bounds, BoundsExtension},
structs::{Point, Position, Size, Rect},
widget::{WidgetContainer, Widget},
properties::*,
structs::*,
widget::{Widget, WidgetContainer},
};
pub fn check_mouse_condition(position: Point, widget: &WidgetContainer<'_>) -> bool {
if let Ok(bounds) = widget.borrow_property::<Bounds>() {
let mut rect = Bounds::from(Rect::new(0.0, 0.0, bounds.width(), bounds.height()));
/// Checks if the given point is inside of a widget.
pub fn check_mouse_condition(mouse_position: Point, widget: &WidgetContainer<'_>) -> bool {
let bounds = widget.get::<Bounds>();
let position = widget.get::<Point>();
if let Ok(g_pos) = widget.borrow_property::<Point>() {
rect.set_x(g_pos.x);
rect.set_y(g_pos.y);
}
let mut rect = Bounds::from(Rect::new(0.0, 0.0, bounds.width(), bounds.height()));
return rect.contains((position.x, position.y));
}
rect.set_x(position.x);
rect.set_y(position.y);
false
return rect.contains((mouse_position.x, mouse_position.y));
}
/// Describes a mouse button.
pub enum MouseButton {
Left,
Middle,
......@@ -97,7 +96,7 @@ pub trait ClickHandler: Sized + Widget {
/// Inserts a handler.
fn on_click<H: Fn(Point) -> bool + 'static>(self, handler: H) -> Self {
self.insert_handler(ClickEventHandler {
handler: Rc::new(handler)
handler: Rc::new(handler),
})
}
}
\ No newline at end of file
}
......@@ -4,8 +4,6 @@ use std::{
rc::Rc,
};
use orbclient::Renderer;
use dces::prelude::{Entity, EntityComponentManager};
use crate::{
......@@ -64,16 +62,16 @@ impl Layout for FixedSizeLayout {
// -- todo will be removed after orbgl merge --
let size = {
if widget.has_property::<Image>() {
if let Ok(image) = widget.borrow_property::<Image>() {
if widget.has::<Image>() {
if let Ok(image) = widget.borrow::<Image>() {
Some((image.width(), image.height()))
} else {
None
}
} else if widget.has_property::<Text>() {
let text = widget.property::<Text>();
let font = widget.property::<Font>();
let font_size = widget.property::<FontSize>();
} else if widget.has::<Text>() {
let text = widget.get::<Text>();
let font = widget.get::<Font>();
let font_size = widget.get::<FontSize>();
if text.0.is_empty() {
if let Ok(water_mark) = ecm.borrow_component::<WaterMark>(entity) {
......@@ -93,15 +91,15 @@ impl Layout for FixedSizeLayout {
}
Some(size)
}
} else if widget.has_property::<FontIcon>() {
let font_icon = widget.property::<FontIcon>();
} else if widget.has::<FontIcon>() {
let font_icon = widget.get::<FontIcon>();
if font_icon.0.is_empty() {
None
} else {
Some(FONT_MEASURE.measure(
&font_icon.0,
&(widget.property::<IconFont>().0).0,
widget.property::<IconSize>().0 as u32,
&(widget.get::<IconFont>().0).0,
widget.get::<IconSize>().0 as u32,
))
}
} else {
......@@ -119,7 +117,6 @@ impl Layout for FixedSizeLayout {
// -- todo will be removed after orbgl merge --
let constraint = Constraint::get(entity, ecm);
let sub_constraint = Constraint::get(entity, ecm);
if constraint.width() > 0.0 {
self.desired_size.borrow_mut().set_width(constraint.width());
......
......@@ -112,13 +112,13 @@ impl Layout for ScrollLayout {
parent_size.0,
self.desired_size.borrow().width(),
margin.left(),
margin.right()
margin.right(),
),
vertical_alignment.align_measure(
parent_size.1,
self.desired_size.borrow().height(),
margin.top(),
margin.bottom()
margin.bottom(),
),
));
......@@ -135,13 +135,10 @@ impl Layout for ScrollLayout {
// horizontal_scroll_mode = mode.horizontal;
// }
let mut offset = (0.0, 0.0);
let old_child_size = self.old_child_size.get();
let off = Offset::get(entity, ecm);
let mut offset = (off.0, off.1);
offset = (off.0, off.1);
let old_child_size = self.old_child_size.get();
for child in &tree.children[&entity] {
// let child_margin = get_margin(*child, ecm);
......@@ -166,7 +163,7 @@ impl Layout for ScrollLayout {
size.1,
child_bounds.height(),
child_margin.top(),
child_margin.bottom()
child_margin.bottom(),
));
}
......
......@@ -116,10 +116,10 @@ impl Layout for TextSelectionLayout {
size.1 = vertical_alignment.align_measure(parent_size.1, size.1, margin.top(), margin.bottom());
if widget.has_property::<Text>() {
let text = widget.property::<Text>();
let font = widget.property::<Font>();
let font_size = widget.property::<FontSize>();
if widget.has::<Text>() {
let text = widget.get::<Text>();
let font = widget.get::<Font>();
let font_size = widget.get::<FontSize>();
if let Ok(selection) = ecm.borrow_component::<TextSelection>(entity) {
if let Some(text_part) = text.0.get(0..selection.0.start_index) {
......
......@@ -52,7 +52,8 @@ macro_rules! property {
#[macro_export]
macro_rules! widget {
( $(#[$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};
#[allow(dead_code)]
use std::{ any::TypeId, rc::Rc, collections::HashMap, cell::RefCell };
use dces::prelude::{Component, ComponentBox, SharedComponentBox };
......@@ -62,6 +63,7 @@ macro_rules! widget {
structs::Point};
$(#[$widget_doc])*
#[derive(Default)]
pub struct $widget {
attached_properties: HashMap<TypeId, ComponentBox>,
shared_attached_properties: HashMap<TypeId, SharedComponentBox>,
......@@ -74,12 +76,16 @@ macro_rules! widget {
margin: Margin,
enabled: Enabled,
visibility: Visibility,
_empty: Option<RefCell<i32>>,
$(
$(
$property: Option<PropertySource<$property_type>>,
)*
)*
children: Vec<Entity>,
$(
state: RefCell<Option<Rc<$state>>>
)*
}
impl $widget {
......@@ -195,6 +201,20 @@ macro_rules! widget {
self
}
$(
/// Returns the cloned state of the widget.
pub fn clone_state(&self) -> Rc<$state> {
if let Some(state) = &*self.state.borrow() {
return state.clone();
}
let state = Rc::new($state::default());
*self.state.borrow_mut() = Some(state.clone());
state
}
)*
$(
$(
$(#[$prop_doc])*
......@@ -219,16 +239,7 @@ macro_rules! widget {
impl Widget for $widget {
fn create() -> Self {
$widget {
attached_properties: HashMap::new(),
shared_attached_properties: HashMap::new(),
event_handlers: vec![],
bounds: Bounds::default(),
constraint: Constraint::default(),
name: None,
horizontal_alignment: HorizontalAlignment::default(),
vertical_alignment: VerticalAlignment::default(),
visibility: Visibility::default(),
margin: Margin::default(),
enabled: Enabled(true),
$(
$(
......@@ -236,6 +247,7 @@ macro_rules! widget {
)*
)*
children: vec![],
..Default::default()
}
}
......@@ -251,7 +263,15 @@ macro_rules! widget {
$(
fn state(&self) -> Option<Rc<State>> {
Some(Rc::new($state::default()))
if self.state.borrow().is_none() {
*self.state.borrow_mut() = Some(Rc::new($state::default()));
}
if let Some(state) = &*self.state.borrow() {
return Some(state.clone())
}
None
}
)*
......@@ -267,8 +287,8 @@ macro_rules! widget {
context.register_layout(entity, this.layout());
// register state
if let Some(state) = this.state() {
context.register_state(entity, state);
if let Some(state) = &this.state() {
context.register_state(entity, state.clone());
}
// register default set of properties
......
......@@ -13,3 +13,12 @@ impl Default for ScrollMode {
ScrollMode::Auto
}
}
impl From<(&str)> for ScrollMode {
fn from(s: &str) -> ScrollMode {
match s {
"Auto" | "auto" => ScrollMode::Auto,
_ => ScrollMode::None
}
}
}
\ No newline at end of file
use super::ScrollMode;
/// `ScrollViewerMode` describes the vertical and horizontal scroll behavior of the `ScrollViewer`.
/// `ScrollViewerMode` describes the vertical and horizontal scroll behavior of the `ScrollViewer`.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct ScrollViewerModeValue {
/// Vertical scroll mode.
......@@ -14,7 +14,7 @@ impl Default for ScrollViewerModeValue {
fn default() -> ScrollViewerModeValue {
ScrollViewerModeValue {
vertical: ScrollMode::Auto,
horizontal: ScrollMode::Auto
horizontal: ScrollMode::Auto,
}
}
}
......@@ -23,3 +23,20 @@ property!(
/// `ScrollViewerMode` describes the vertical and horizontal scroll behavior of the `ScrollViewer`.
ScrollViewerMode(ScrollViewerModeValue)
);
// --- Conversions ---
impl From<(&str, &str)> for ScrollViewerMode {
fn from(s: (&str, &str)) -> ScrollViewerMode {
ScrollViewerMode(ScrollViewerModeValue {
vertical: ScrollMode::from(s.0),
horizontal: ScrollMode::from(s.1),
})
}
}
impl Into<PropertySource<ScrollViewerMode>> for (&str, &str) {
fn into(self) -> PropertySource<ScrollViewerMode> {
PropertySource::Value(ScrollViewerMode::from(self))
}
}
\ No newline at end of file
......@@ -21,7 +21,7 @@ impl fmt::Debug for InnerFont {
impl PartialEq for InnerFont {
// todo: impl
fn eq(&self, other: &InnerFont) -> bool {
fn eq(&self, _other: &InnerFont) -> bool {
false
}
}
......
use std::fmt;
use orbfont::Font as OrbFont;
use crate::styling::fonts;
use super::InnerFont;
property!(
......
property!(
/// `Opacity` describes tthe opacity of a widget.
/// `Opacity` describes the opacity of a widget.
Opacity(f64)
);
......@@ -40,11 +40,10 @@ pub struct SelectorValue {
}
impl fmt::Display for SelectorValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(element) = &self.element {
return write!(f, ", css: {}", element);
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(element) = &self.element {
return write!(f, ", css: {}", element);
}
write!(f, "")
}
......
......@@ -21,7 +21,7 @@ impl fmt::Debug for InnerImage {
impl PartialEq for InnerImage {
// todo: impl
fn eq(&self, other: &InnerImage) -> bool {
fn eq(&self, _other: &InnerImage) -> bool {
false
}
}
......
......@@ -25,7 +25,7 @@ impl RenderObject for FontIconRenderObject {
global_position: &Point,
) {
let parent_bounds = if let Some(parent) = context.parent_widget() {
if let Ok(bounds) = parent.borrow_property::<Bounds>() {
if let Ok(bounds) = parent.borrow::<Bounds>() {
bounds.clone()
} else {
Bounds::default()
......@@ -35,17 +35,17 @@ impl RenderObject for FontIconRenderObject {
};
let widget = context.widget();
let icon = widget.property::<FontIcon>();
let icon = widget.get::<FontIcon>();
if !icon.0.is_empty() {
renderer.render_text(
&icon.0,
&widget.property::<Bounds>(),
widget.borrow::<Bounds>().unwrap(),
&parent_bounds,
global_position,
widget.property::<IconSize>().0 as u32,
widget.property::<IconBrush>().into(),
&(widget.property::<IconFont>().0).0,
widget.get::<IconSize>().0 as u32,
widget.get::<IconBrush>().into(),
&(widget.get::<IconFont>().0).0,
);
}
}
......
......@@ -26,9 +26,9 @@ impl RenderObject for ImageRenderObject {
global_position: &Point,
) {
let mut widget = context.widget();
let bounds = widget.property::<Bounds>();
let bounds = widget.get::<Bounds>();
if let Ok(image) = widget.borrow_mut_property::<Image>() {
if let Ok(image) = widget.borrow_mut::<Image>() {
canvas.draw_image_with_size(&mut (image.0).0, global_position.x, global_position.y, bounds.width(), bounds.height());
}
}
......
......@@ -152,11 +152,11 @@ impl RenderObject for RectangleRenderObject {
) {
let widget = context.widget();
let bounds = widget.property::<Bounds>();
let background = widget.property::<Background>();
let border_radius = widget.property::<BorderRadius>();
let border_thickness = widget.property::<BorderThickness>();
let border_brush = widget.property::<BorderBrush>();
let bounds = widget.get::<Bounds>();
let background = widget.get::<Background>();
let border_radius = widget.get_or_default::<BorderRadius>();
let border_thickness = widget.get_or_default::<BorderThickness>();
let border_brush = widget.get_or_default::<BorderBrush>();
let has_thickness = border_thickness.0.left > 0.0
|| border_thickness.0.top > 0.0
......
......@@ -26,7 +26,7 @@ impl RenderObject for TextRenderObject {
global_position: &Point,
) {
let parent_bounds = if let Some(parent) = context.parent_widget() {
if let Ok(bounds) = parent.borrow_property::<Bounds>() {
if let Ok(bounds) = parent.borrow::<Bounds>() {
bounds.clone()
} else {
Bounds::default()
......@@ -36,17 +36,17 @@ impl RenderObject for TextRenderObject {
};
let widget = context.widget();
let text = widget.property::<Text>();
let text = widget.get::<Text>();
if !text.0.is_empty() {
renderer.render_text(
&text.0,
&widget.property::<Bounds>(),
&widget.get::<Bounds>(),
&parent_bounds,
global_position,
widget.property::<FontSize>().0 as u32,
widget.property::<Foreground>().into(),
&(widget.property::<Font>().0).0,
widget.get::<FontSize>().0 as u32,
widget.get::<Foreground>().into(),
&(widget.get::<Font>().0).0,
);
}
}
......
use orbfont::Font;
use std::collections::HashMap;
/// Reference to the material icon font.
pub static MATERIAL_ICONS_REGULAR_FONT: &'static [u8; 128180] =
......
......@@ -60,7 +60,7 @@ impl EventSystem {
// MouseUpEvent handling
if event.event_type() == TypeId::of::<MouseUpEvent>() {
if let Ok(pressed) = widget.borrow_property::<Pressed>() {
if let Ok(pressed) = widget.borrow::<Pressed>() {
if pressed.0 {
matching_nodes.push(node);
break;
......@@ -115,13 +115,13 @@ impl EventSystem {
// MouseDownEvent handling
if event.event_type() == TypeId::of::<MouseDownEvent>() {
if let Ok(focused) = widget.borrow_mut_property::<Focused>() {
if let Ok(focused) = widget.borrow_mut::<Focused>() {
focused.0 = true;
new_focused_widget = Some(*node);
self.update.set(true);
}
if let Ok(pressed) = widget.borrow_mut_property::<Pressed>() {
if let Ok(pressed) = widget.borrow_mut::<Pressed>() {
pressed.0 = true;
self.update.set(true);
}
......@@ -137,13 +137,13 @@ impl EventSystem {
}
if in_mouse_pos {
if let Ok(selected) = widget.borrow_mut_property::<Selected>() {
if let Ok(selected) =