This commit is contained in:
2025-06-30 12:19:17 -05:00
parent c2a3899fe1
commit 915dabe9e2
17 changed files with 773 additions and 1 deletions
@@ -7,7 +7,7 @@ This macro is the recommended way to describe a ui, it is a div that holds multi
fn app() -> Element {
rsx! {
button { "click me" }
text { "This is some text" }
text { "This is some text" }****
}
}
```
+40
View File
@@ -0,0 +1,40 @@
---
title: Engine
slug: /engine
---
The OSUI engine is what goes on under the hood. You might need this on special ocasions (Game engine, Custom animation, Physics, etc) because it's easier to manipulate. Here's an example of an element moving with a velocity of 50:
```rust
use osui::prelude::*;
fn main() -> Result<()> {
let mut con = console::init(true)?;
let velocity = 50;
let mut position = use_state(0);
loop {
con.draw(app(*position), None)?;
std::thread::sleep(std::time::Duration::from_millis(1000 / velocity));
position += 1;
if position + 13 > con.size().0 {
break;
}
}
con.end()
}
pub fn app(pos: u16) -> Element {
std::sync::Arc::new(move |frame, _event| -> Result<()> {
frame.draw(
&"Hello, World!",
Area {
x: Pos::Num(pos),
..Default::default()
},
)?;
Ok(())
})
}
```
+54
View File
@@ -0,0 +1,54 @@
---
title: Introduction
slug: /
---
## Installation
On a cargo project run
```bash
cargo add osui
```
## Hello world
```rust title='src/main.rs'
use osui::prelude::*;
fn main() -> Result<()> {
let mut con = console::init(true)?;
con.run(app())?;
con.end()
}
pub fn app() -> Element {
rsx! {
"Hello, World!"
}
}
```
## Counter
```rust title='src/main.rs'
use osui::prelude::*;
fn main() -> Result<()> {
let mut con = console::init(true)?;
con.run(app())?;
con.end()
}
pub fn app() -> Element {
let count = use_state(0);
rsx! {
button { on_click: move |_| count+=1, "{count}" }
}
}
```
@@ -0,0 +1,96 @@
---
title: RSX
---
This macro is the recommended way to describe a ui, it is a div that holds multiple elements
```rust
fn app() -> Element {
rsx! {
button { "click me" }
text { "This is some text" }
}
}
```
> :::info `rsx!` is really just a div, so you can just do something like
> ```rust
> rsx! {
> id: "root", class: "root",
>
> button { "click me" }
> text { "This is some text" }
> }
> ```
## Child values
If you want to add more children to values then just simply express it like a `rsx!`
```rust
fn app() -> Element {
let x = 69;
rsx! {
div {
text { "the number is {x}, Nice!" }
}
}
}
```
## Formatted text
```rust
fn app() -> Element {
let x = 69;
rsx! {
text { "the number is {x}, Nice!" }
}
}
```
> :::info You can also do expressions after the string
```rust
text { "the number is {}, Nice!", x }
```
## For loops
```rust
fn app() -> Element {
rsx! {
for (i in 0..5) { // () are required
text { "{i}" }
}
}
}
```
## Attribute
You can change the element's struct fields by just providing some attributes before the children
```rust
fn app() -> Element {
rsx! {
text { class: "my_text" }
}
}
```
## Type assignment
In special elements like `data_holder` You can specify what `type` the element holds. It would act like `my_fn::<Type>()`
```rust
fn app() -> Element {
rsx! {
// assign the type u32
data_holder as u32 { id: "count" }
}
}
```
## Handler functions
Instead of closures which are tricky to work with on structs, We use `Handler`, It's basically a closure wrapped with a `Arc<Mutex<T>>`
```rust
fn app() -> Element {
rsx! {
button {
on_click: fn(btn: &mut Button, event, document) {
// do something
}
}
}
}
```
@@ -0,0 +1,24 @@
---
title: Handler
---
A `Handler` is a closure wrapper. Due to how closures work, they aren't the best to work with on structs (in this case: elements). So to fix this we use a `Handler` which is a wrapper for the closure, Then you can safely clone and use it without any problems (in which a normal closure would fail at)
## Examples
```rust
Handler::new(|btn: &mut Button, event, document| {
// do something
})
```
A better way to do this is:
```rust
rsx! {
button {
// No need for Handler::new
on_click: fn(btn: &mut Button, event, document) {
// do something
}
}
}
```
> :::info `fn() {}` is a part of our macro `rsx!`. In rust you would normally use `|| {}`
@@ -0,0 +1,66 @@
---
title: CSS
---
Along with the `Css` type, This macro provides styling for multiple elements by their class name or struct name.
## Style by classname
```rust
fn app() -> Element {
rsx! {
styling: Some(styles()) // Set the css styling for the div.
button { class: "my_btn", "Click me!" }
}
}
fn styles() -> Css {
css! {
.my_btn { // style by classname
color: Red,
}
}
}
```
## Style by state
```rust
fn app() -> Element {
rsx! {
styling: Some(styles()) // Set the css styling for the div.
button { class: "my_btn", "Click me!" }
}
}
fn styles() -> Css {
css! {
.my_btn: clicked { // When the element state is clicked
color: Blue,
}
}
}
```
## Style by struct name
```rust
fn app() -> Element {
rsx! {
styling: Some(styles()) // Set the css styling for the div.
button { "Click me!" } // No need for classes
}
}
fn styles() -> Css {
css! {
Button { // style by the struct name
color: Red,
}
Button: clicked { // When the element state is clicked
color: Blue,
}
}
}
```
@@ -0,0 +1,20 @@
---
title: Style
---
Like `css!`, `style!` is a way to style a element. But unlike `css!`, `style!` is only meant to style a single element
```rust
rsx! {
button {
style: style! {
color: Red,
clicked { // when the button state is 'clicked'
color: Blue,
}
},
"click me!"
}
}
```
@@ -0,0 +1,28 @@
---
title: Document
---
The `Document` holds the root element and it renders and passes events to the `Element`. It's important for updating the UI.
## Example
```rust
fn(_, _, document) {
if let Some(my_text) = document.get_element_by_id::<Text>("my_text") {
my_text.children.set_text("Updated!");
}
}
```
## Methods
### `exit()`
Exits the program
### `restart()`
Restarts the program
### `get_element_by_id<T>(id: &str) -> Option<&mut Box<T>>`
Retrieves a mutable reference to a boxed element of type T by its string identifier, returning None if no such element exists.
> :::info Please make sure that the type of the element is correctly matched to the element of that id
### `get_element_by_id_raw(id: &str) -> Option<&mut Element>`
> :::warning Not recommended to use this function, Use `get_element_by_id` instead
Retrieves a mutable reference to a boxed element by its string identifier, returning None if no such element exists
### `render()`
Renders/reloads the screen, useful when a element updates
@@ -0,0 +1,5 @@
---
title: Element
---
`Element` is a type alias of `Box<dyn ElementWidget>`. It makes the code look cleaner
@@ -0,0 +1,14 @@
---
title: ElementWidget
---
`ElementWidget` is a trait that defines the Elements and it's rendering / event updates.
## Methods
### `render(&self, focused: bool) -> Option<RenderResult>`
- **required**
- This function renders the element
### `event(&mut self, event: Event, document: &Document)`
- **optional**
- This function updates the element when there is a event
@@ -0,0 +1,32 @@
---
title: ElementCore
---
`ElementCore` is a trait that will automatically be implemented by the `osui_element::element` proc-macro. All of it's functions are used by OSUI.
## `element` proc-macro
This macro adds the essential fields and functions for a `ElementCore` structure.
```rust
use osui_element::element;
#[element]
#[derive(Default, Debug)]
struct MyElement {}
```
## `elem_fn` proc-macro
This macro makes a function that returns a `Box<T>` of which T is the default of `MyElement`
```rust
use osui_element::{element, elem_fn};
#[element]
#[elem_fn]
#[derive(Default, Debug)]
struct MyElement {}
```
>:::info
>You can also define a function for the element manually:
>```rust
>pub fn my_element() -> Box<MyElement> {
> Box::new(MyElement::default())
>}
>```