Commit 07cc4778 authored by Michael Aaron Murphy's avatar Michael Aaron Murphy

Merge branch 'layout-update' into 'master'

Layout and API update

See merge request !101
parents 1862d863 f8240326
Pipeline #2852 passed with stages
in 4 minutes and 58 seconds
......@@ -59,6 +59,17 @@
"rust"
]
},
{
"type": "lldb",
"request": "launch",
"name": "Debug grid",
"program": "${workspaceFolder}/target/debug/examples/grid",
"cwd": "${workspaceFolder}",
"preLaunchTask": "build",
"sourceLanguages": [
"rust"
]
},
{
"type": "lldb",
"request": "launch",
......
......@@ -9,7 +9,7 @@
"type": "shell",
"args": [
"build",
"--examples=widgets"
"--examples=minimal"
],
"presentation": {
"reveal": "always",
......
This diff is collapsed.
......@@ -24,8 +24,10 @@ path = "src/lib.rs"
[dependencies]
cssparser = "0.17.0"
lazy_static = "1.2.0"
# dces = { path = "../dces-rust"}
dces = { git = "https://gitlab.redox-os.org/redox-os/dces-rust.git" }
orbclient = "0.3.18"
orbclient = "0.3.20"
orbfont = { git = "https://gitlab.redox-os.org/redox-os/orbfont.git" }
orbimage = "0.1.16"
orbgl = { git = "https://gitlab.redox-os.org/redox-os/orbgl.git", rev = "ae7c4679fc37457f843c1c1446fcb7e55f457857" }
orbgl = { git = "https://gitlab.redox-os.org/redox-os/orbgl.git" }
orbgl_shapes = { git = "https://gitlab.redox-os.org/redox-os/orbgl.git" }
......@@ -10,7 +10,7 @@
The Orbital Widget Toolkit is a multi platform (G)UI toolkit for building scalable user interfaces with the programming language Rust. It's based
on the [Entity Component System Pattern](https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system) and provides a functional-reactive API.
The main goals of OrbTk are fast peformance, easy to use and cross platform.
The main goals of OrbTk are fast performance, easy to use and cross platform.
<img alt="Calculator" height="300" src="https://gitlab.redox-os.org/redox-os/assets/raw/master/screenshots/Calculator.png">
......@@ -18,7 +18,7 @@ The main goals of OrbTk are fast peformance, easy to use and cross platform.
* Modern [Flutter](https://flutter.io/), [React](https://reactjs.org/), [Redux](https://redux.js.org/) like API
* Uses the Entity Component System library [DCES](https://gitlab.redox-os.org/redox-os/dces-rust) for widget and properties handling
* Updating instead of rebuilding subtrees
* Updating instead of rebuilding sub-trees
* Flexible event system
* Widget state management
* Cross platform: Redox OS, Linux, macOS, Windows
......@@ -47,30 +47,16 @@ crate](https://github.com/AngryLawyer/rust-sdl2#user-content-requirements).
## Minimal Example
```rust
extern crate orbtk;
use orbtk::*;
struct MainView;
impl Widget for MainView {
fn create() -> Template {
Template::default()
.as_parent_type(ParentType::Single)
.with_child(
Container::create()
.as_parent_type(ParentType::Single)
.with_child(TextBlock::create().with_property(Label::from("OrbTk"))),
)
}
}
fn main() {
let mut application = Application::default();
application
.create_window()
.with_bounds(Bounds::new(0, 0, 420, 730))
.with_title("OrbTk")
.with_root(MainView::create())
.bounds(Bounds::new(100.0, 100.0, 420.0, 730.0))
.title("OrbTk - minimal example")
.root(TextBlock::create().text("OrbTk").into())
.debug_flag(false)
.build();
application.run();
}
......@@ -86,7 +72,7 @@ You can start the widgets example by executing the following command:
cargo run --example widgets --release
```
## Build and run documenation
## Build and run documentation
You can build and run the latest documentation y executing the following command:
......
......@@ -3,80 +3,13 @@ use orbtk::*;
struct MainView;
impl Widget for MainView {
fn create() -> Template {
let mut canvas = Canvas::new(800.0, 600.0);
//Transform the canvas
canvas.transform(2.83, -2.83, 2.83, 2.83, 150.0, 300.0);
//Set canvas fill style
canvas.set_fill_style(Color::rgba(0, 0, 0, 255));
type Template = Template;
canvas.begin_path();
canvas.move_to(48.355, 17.922);
canvas.bezier_curve_to(52.06, 20.245, 54.658, 24.176, 55.131, 28.739);
canvas.bezier_curve_to(56.642, 29.445, 58.319, 29.851, 60.097, 29.851);
canvas.bezier_curve_to(66.588, 29.851, 71.849, 24.59, 71.849, 18.1);
canvas.bezier_curve_to(71.849, 11.609, 66.588, 6.348, 60.097, 6.348);
canvas.bezier_curve_to(53.668, 6.35, 48.453, 11.517, 48.355, 17.922);
canvas.close_path();
canvas.move_to(40.656, 41.984);
canvas.bezier_curve_to(47.147, 41.984, 52.408, 36.722, 52.408, 30.232);
canvas.bezier_curve_to(52.408, 23.742, 47.146, 18.481, 40.656, 18.481);
canvas.bezier_curve_to(34.166, 18.481, 28.902, 23.743, 28.902, 30.233);
canvas.bezier_curve_to(28.902, 36.723, 34.166, 41.984, 40.656, 41.984);
canvas.close_path();
canvas.move_to(45.641, 42.785);
canvas.line_to(35.669, 42.785);
canvas.bezier_curve_to(27.372, 42.785, 20.622, 49.536, 20.622, 57.833);
canvas.line_to(20.622, 70.028);
canvas.line_to(20.653, 70.219);
canvas.line_to(21.493, 70.482);
canvas.bezier_curve_to(29.411, 72.956, 36.290, 73.781, 41.952, 73.781);
canvas.bezier_curve_to(53.011, 73.781, 59.421, 70.628, 59.816, 70.427);
canvas.line_to(60.601, 70.03);
canvas.line_to(60.685, 70.03);
canvas.line_to(60.685, 57.833);
canvas.bezier_curve_to(60.688, 49.536, 53.938, 42.785, 45.641, 42.785);
canvas.close_path();
canvas.move_to(65.084, 30.653);
canvas.line_to(55.189, 30.653);
canvas.bezier_curve_to(55.082, 34.612, 53.392, 38.177, 50.719, 40.741);
canvas.bezier_curve_to(58.094, 42.934, 63.49, 49.773, 63.49, 57.851);
canvas.line_to(63.49, 61.609);
canvas.bezier_curve_to(73.26, 61.251, 78.89, 58.482, 79.261, 58.296);
canvas.line_to(80.046, 57.898);
canvas.line_to(80.13, 57.898);
canvas.line_to(80.13, 45.699);
canvas.bezier_curve_to(80.13, 37.403, 73.38, 30.653, 65.084, 30.653);
canvas.close_path();
canvas.move_to(20.035, 29.853);
canvas.bezier_curve_to(22.334, 29.853, 24.473, 29.182, 26.285, 28.039);
canvas.bezier_curve_to(26.861, 24.282, 28.875, 20.999, 31.752, 18.763);
canvas.bezier_curve_to(31.764, 18.543, 31.785, 18.325, 31.785, 18.103);
canvas.bezier_curve_to(31.785, 11.612, 26.523, 6.351, 20.035, 6.351);
canvas.bezier_curve_to(13.543, 6.351, 8.283, 11.612, 8.283, 18.103);
canvas.bezier_curve_to(8.283, 24.591, 13.543, 29.853, 20.035, 29.853);
canvas.close_path();
canvas.move_to(30.589, 40.741);
canvas.bezier_curve_to(27.929, 38.19, 26.245, 34.644, 26.122, 30.709);
canvas.bezier_curve_to(25.755, 30.682, 25.392, 30.653, 25.018, 30.653);
canvas.line_to(15.047, 30.653);
canvas.bezier_curve_to(6.75, 30.653, 0.0, 37.403, 0.0, 45.699);
canvas.line_to(0.0, 57.896);
canvas.line_to(0.031, 58.084);
canvas.line_to(0.871, 58.349);
canvas.bezier_curve_to(7.223, 60.332, 12.892, 61.246, 17.816, 61.534);
canvas.line_to(17.816, 57.851);
canvas.bezier_curve_to(17.818, 49.773, 23.212, 42.936, 30.589, 40.74);
//Fill the polygon and draw a stroke
canvas.fill();
Template::default()
.as_parent_type(ParentType::Single)
.with_debug_name("MainView")
.with_child(CanvasWidget::create().with_property(canvas))
fn create() -> Template {
Template::new()
.parent_type(ParentType::Single)
.debug_name("MainView")
.child(TextBlock::create().text("Wait for next merge"))
}
}
......@@ -84,9 +17,9 @@ fn main() {
let mut application = Application::default();
application
.create_window()
.with_bounds(Bounds::new(100, 100, 800, 600))
.with_title("OrbTk - canvas example")
.with_root(MainView::create())
.bounds((100.0, 100.0, 800.0, 600.0))
.title("OrbTk - canvas example")
.root(MainView::create())
.build();
application.run();
}
debugborder {
border-width: 1;
border-radius: 0;
border-color: white;
background: transparent;
}
row.full {
width: 600;
}
column.navview {
width: 400;
}
container.navbarview {
padding: 0;
}
center.navtitleview {
width: 400;
height: 32;
}
textblock.navtitle {
font-size: 18;
width: 100;
min-width: 150;
}
button.nav {
width: 100;
}
container.mainviewbox {
padding: 0;
}
center.mainviewbox {
width:200;
height:300;
}
extern crate orbtk;
use orbtk::*;
use std::{rc::Rc};
static CENTER_DEMO_CSS: &'static str = include_str!("center-demo.css");
#[derive(Default)]
struct MainViewState {}
impl MainViewState {}
impl State for MainViewState {
}
struct MainView;
impl Widget for MainView {
fn create() -> Template {
let state = Rc::new(MainViewState::default());
let label = SharedProperty::new(Label::from("prototype"));
Template::default()
.as_parent_type(ParentType::Single)
.with_state(state.clone())
// Nav bar
.with_child(Column::create()
.with_child(build_navbar())
.with_child(build_main_view())
)
.with_shared_property(label)
.with_debug_name("MainView")
}
}
// Create a row for buttons and information
fn build_navbar() -> Template {
let frame = Constraint::default()
.with_width(400)
.with_height(50)
.with_min_width(400);
Row::create().with_property(Selector::from("row").with_class("full"))
.with_child(Column::create()
.with_child(Button::create()
.with_property(Selector::from("button").with_class("nav"))
.with_property(Label::from("Home")),
),
)
.with_child(Column::create()
.with_layout(FixedSizeLayout::default())
.with_property(Selector::from("column").with_class("navview"))
.with_child(Container::create()
.with_property(Selector::from("container").with_class("navbarview"))
.with_child(Center::create()
.with_property(frame)
.with_property(Selector::from("center").with_class("navtitleview"))
.with_child(TextBlock::create()
.with_property(Label::from("TITLE"))
.with_property(Selector::from("textblock").with_class("navtitle")),
))))
.with_child(Column::create()
.with_child(Button::create()
.with_property(Selector::from("button").with_class("nav"))
.with_property(Label::from("Settings")),
),
)
}
fn build_main_view() -> Template {
Row::create()
.with_child(build_boxview("Step 1"))
.with_child(build_boxview("Step 2"))
.with_child(build_boxview("Step 3"))
}
fn build_boxview(title: &str) -> Template {
Column::create()
.with_child(Container::create()
.with_property(Selector::from("container").with_class("mainviewbox"))
.with_child(Center::create()
.with_property(Selector::from("center").with_class("mainviewbox"))
.with_child(Button::create()
.with_property(Selector::from("button").with_class("primary"))
.with_property(Label::from(title)),
)))
}
fn main() {
let mut application = Application::default();
application
.create_window()
.with_bounds(Bounds::new(100, 200, 600, 400))
.with_title("Fixed and center layouts")
.with_theme(Theme::create()
.with_extenstion_css(CENTER_DEMO_CSS)
.build(),
)
.with_root(MainView::create())
.with_debug_flag(false)
.build();
application.run();
}
use orbtk::*;
struct MainView;
impl Widget for MainView {
type Template = Template;
fn create() -> Self::Template {
Template::new()
.child(
Grid::create()
.columns(
Columns::create()
.column("*")
.column("Auto")
.column(50.0)
.build(),
)
.rows(Rows::create().row("*").row("*").build())
.child(
Grid::create()
.selector("lynch")
.margin((10.0, 0.0, 0.0, 4.0))
.attach_property(GridColumn(0))
.child(
TextBlock::create()
.text("(0,0)")
.horizontal_alignment("Center")
.vertical_alignment("Center"),
),
)
.child(
Grid::create()
.selector("bluebayoux")
.margin(10.0)
.constraint(Constraint::create().width(150.0).build())
.attach_property(GridColumn(1))
.child(
TextBlock::create()
.text("(1,0)")
.horizontal_alignment("Center")
.vertical_alignment("Center"),
),
)
.child(
Grid::create()
.selector("linkwater")
.attach_property(GridColumn(2))
.child(
TextBlock::create()
.text("(2,0)")
.selector("linkwater")
.horizontal_alignment("Center")
.vertical_alignment("Center"),
),
)
.child(
Grid::create()
.selector("goldendream")
.attach_property(GridColumn(0))
.attach_property(GridRow(1))
.attach_property(ColumnSpan(3))
.child(
TextBlock::create()
.text("(0,1) - ColumnSpan 3")
.selector("goldendream")
.horizontal_alignment(HorizontalAlignment(Alignment::Center))
.vertical_alignment(VerticalAlignment(Alignment::Center)),
),
),
)
.debug_name("MainView")
}
}
fn main() {
let mut application = Application::default();
application
.create_window()
.bounds((100.0, 100.0, 420.0, 730.0))
.title("OrbTk - grid example")
.root(MainView::create())
.theme(
Theme::create()
.extension_path("examples/res/grid.css")
.build(),
)
.resizable(true)
.build();
application.run();
}
......@@ -3,14 +3,12 @@ use orbtk::*;
struct MainView;
impl Widget for MainView {
fn create() -> Template {
Template::default()
.as_parent_type(ParentType::Single)
.with_debug_name("MainView")
.with_child(
ImageWidget::create()
.with_property(Image::from_path("res/orbtk-space.png").unwrap()),
)
type Template = Template;
fn create() -> Self::Template {
Template::new()
.debug_name("MainView")
.child(ImageWidget::create().image("res/orbtk-space.png"))
}
}
......@@ -18,9 +16,9 @@ fn main() {
let mut application = Application::default();
application
.create_window()
.with_bounds(Bounds::new(100, 100, 800, 420))
.with_title("OrbTk - image example")
.with_root(MainView::create())
.bounds((100.0, 100.0, 800.0, 420.0))
.title("OrbTk - image example")
.root(MainView::create())
.build();
application.run();
}
use orbtk::*;
use std::cell::Cell;
use std::rc::Rc;
use std::{cell::Cell, rc::Rc};
#[derive(Default)]
struct MainViewState {
......@@ -16,91 +15,115 @@ impl MainViewState {
impl State for MainViewState {
fn update(&self, context: &mut Context<'_>) {
if let Ok(button_count_label) = context.widget().borrow_mut_property::<Label>() {
button_count_label.0 = format!("Button count: {}", self.counter.get());
if let Ok(button_count_text) = context.widget().borrow_mut_property::<Text>() {
button_count_text.0 = format!("Button count: {}", self.counter.get());
}
}
}
fn create_header(text: &str) -> Template {
fn create_header(text: &str, grid: usize, column: usize) -> Template {
TextBlock::create()
.with_property(Label::from(text))
.with_property(Selector::from("textblock").with_class("h1"))
}
fn create_space_row() -> Template {
Row::create().with_property(Selector::from("row").with_class("space"))
.text(text)
.selector(Selector::from("textblock").class("h1"))
.attach_property(GridColumn(grid))
.attach_property(GridRow(column))
.into()
}
struct MainView;
impl Widget for MainView {
fn create() -> Template {
type Template = Template;
fn create() -> Self::Template {
let state = Rc::new(MainViewState::default());
let button_count_label = SharedProperty::new(Label::from("Button count: 0"));
let button_count_text = SharedProperty::new(Text::from("Button count: 0"));
Template::default()
.as_parent_type(ParentType::Single)
.with_state(state.clone())
.with_child(
create_space_row()
.with_child(
Column::create()
.with_child(Container::create().with_child(create_header("Buttons")))
.with_child(
Container::create().with_child(
Button::create()
.with_property(Label::from("Button"))
.with_property(FontIcon::from(
styling::vector_graphics::material_font_icons::CHECK_FONT_ICON,
))
.with_event_handler(MouseEventHandler::default().on_click(
Rc::new(move |_pos: Point| -> bool {
state.increment();
true
}),
)),
),
)
.with_child(
Container::create().with_child(
Button::create()
.with_property(
Selector::from("button").with_class("primary"),
)
.with_property(Label::from("Primary")),
),
)
.with_child(Container::create().with_child(
ToggleButton::create().with_property(Label::from("ToggleButton")),
))
.with_child(Container::create().with_child(
CheckBox::create().with_property(Label::from("CheckBox")),
))
.with_child(Container::create().with_child(Switch::create())),
Template::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_property(GridColumn(0))
.attach_property(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_property(GridColumn(0))
.attach_property(GridRow(2)),
)
.child(
ToggleButton::create()
.text("ToggleButton")
.margin((0.0, 8.0, 0.0, 0.0))
.attach_property(GridColumn(0))
.attach_property(GridRow(3)),
)
.child(
CheckBox::create()
.text("CheckBox")
.margin((0.0, 8.0, 0.0, 0.0))
.attach_property(GridColumn(0))
.attach_property(GridRow(4)),
)
.child(
Switch::create()
.margin((0.0, 8.0, 0.0, 0.0))
.attach_property(GridColumn(0))
.attach_property(GridRow(5)),
)
// Column 2
.child(create_header("Text", 2, 0))
.child(
TextBlock::create()
.shared_text(button_count_text.clone())
.margin((0.0, 8.0, 0.0, 0.0))
.attach_property(GridColumn(2))
.attach_property(GridRow(1)),
)
.with_child(
Column::create()
.with_child(Container::create().with_child(create_header("Text")))
.with_child(
Container::create().with_child(
TextBlock::create()
.with_shared_property(button_count_label.clone())
.with_property(
Selector::from("textblock").with_class("fheight"),
),
),
)
.with_child(Container::create().with_child(
TextBox::create().with_property(WaterMark::from("TextBox...")),
))
.with_child(Container::create().with_child(
TextBox::create().with_property(WaterMark::from("TextBox...")),
)),
.child(
TextBox::create()