Crate sixtyfps[−][src]
Expand description
SixtyFPS
This crate is the main entry point for embedding user interfaces designed with SixtyFPS UI in Rust programs.
Included in this documentation is also the language reference, documentation of builtin elements, widgets and layouting.
If you are new to SixtyFPS, you might also consider going through our Walk-through tutorial.
How to use:
The user interfaces are described in the .60
design markup language. There are two ways
of including the design in Rust:
- The
.60
code is inline in a macro. - The
.60
code in external files compiled withbuild.rs
This markup code is translated to Rust code and each component is turned into a Rust struct with functions to instantiated, show or access properties. This documentation includes an example of how the API looks like.
The .60 code in a macro
This method combines your Rust code with the .60
design markup in one file, using a macro:
sixtyfps::sixtyfps!{ HelloWorld := Window { Text { text: "hello world"; color: green; } } } fn main() { HelloWorld::new().run(); }
The .60 file in external files compiled with build.rs
This method allows you to a separate .60
file on the file system, which works well if
your design becomes bigger and you split it up across multiple files. You need to use a
so-called build script
to trigger the compilation of the .60
file.
In your Cargo.toml:
[package]
...
build = "build.rs"
[dependencies]
sixtyfps = "0.1.0"
...
[build-dependencies]
sixtyfps-build = "0.1.0"
In the build.rs
file:
fn main() { sixtyfps_build::compile("ui/hello.60").unwrap(); }
Then in your main file
sixtyfps::include_modules!(); fn main() { HelloWorld::new().run(); }
Generated components
As of now, only the last component of a .60 source is generated. It is planned to generate all exported components.
The component is generated and re-exported at the location of the include_modules!
or sixtyfps!
macro.
it consist of a struct of the same name of the component.
For example, if you have export MyComponent := Window { /*...*/ }
in the .60 file, it will create a struct MyComponent{ /*...*/ }
.
This documentation contains a documented generated component: docs::generated_code::SampleComponent
.
The component is created using the fn new() -> Self
function. In addition
the following convenience functions are available through the ComponentHandle
implementation:
fn clone_strong(&self) -> Self
: to create a strongly referenced clone.fn as_weak(&self) -> Weak
: to create a weak reference.fn show(&self)
: to show the window of the component.fn hide(&self)
: to hide the window of the component.fn run(&self)
: a convenience function that first callsshow()
, followed by spinning the event loop, andhide()
when returning from the event loop.
For each top-level property
- A setter
fn set_<property_name>(&self, value: <PropertyType>)
- A getter
fn get_<property_name>(&self) -> <PropertyType>
For each top-level callback
fn invoke_<callback_name>(&self)
: to invoke the callbackfn on_<callback_name>(&self, callback: impl Fn(<CallbackArgs>) + 'static)
: to set the callback handler.
After instantiating the component you can call just ComponentHandle::run()
on it, in order to show it and spin the event loop to
render and react to input events. If you want to show multiple components simultaneously, then you can also call just
ComponentHandle::show()
first. When you’re ready to enter the event loop, just call run_event_loop()
.
The generated component struct act as a handle holding a strong reference (similar to a Rc
). It does not implement
Clone
because we want to make explicit if we are cloning a strong reference (with ComponentHandle::clone_strong
),
or a weak reference (with ComponentHandle::as_weak
). A strong reference should not be captured by the closures
given to a callback, as this would produce a reference loop and leak the component. Instead, the callback function
should capture a weak component.
Threading and Event-loop
For platform-specific reasons, the event loop must run in the main thread, in most backends, and all the components must be created in the same thread as the thread the event loop is running or is going to run.
Ideally, you should perform the minimum amount of work in the main thread and delegate the actual logic to another
thread. To communicate from your worker thread to the UI thread, the invoke_from_event_loop
function can be used.
To run a function with a delay or with an interval you can use a Timer
.
Type Mappings
The types used for properties in .60
design markup each translate to specific types in Rust.
The follow table summarizes the entire mapping:
.60 Type | Rust Type | Note |
---|---|---|
int | i32 | |
float | f32 | |
string | SharedString | A reference-counted string type that can be easily converted to a str reference. |
color | Color | |
brush | Brush | |
image | Image | |
physical_length | f32 | The unit are physical pixels. |
length | f32 | At run-time, logical lengths are automatically translated to physical pixels using the device pixel ratio. |
duration | i64 | At run-time, durations are always represented as signed 64-bit integers with millisecond precision. |
structure | struct of the same name | |
array | ModelHandle |
For user defined structures in the .60, an extra struct is generated.
For example, if the .60
contains
export struct MyStruct := {
foo: int,
bar: string,
}
The following struct would be generated:
#[derive(Default, Clone, Debug, PartialEq)] struct MyStruct { foo : i32, bar: sixtyfps::SharedString, }
Modules
This is a pseudo module which only exist for documentation purposes as a way to show the SixtyFPS documentation as part of rustdoc.
This module contains functions useful for unit tests
Macros
Include the code generated with the sixtyfps-build crate from the build script. After calling sixtyfps_build::compile
in your build.rs
build script, the use of this macro includes the generated Rust code and makes the exported types
available for you to instantiate.
This macro allows you to use the .60
design markup language inline in Rust code. Within the braces of the macro
you can use place .60
code and the named exported components will be available for instantiation.
Structs
Color represents a color in the SixtyFPS run-time, represented using 8-bit channels for red, green, blue and the alpha (opacity). It can be conveniently constructed and destructured using the to_ and from_ (a)rgb helper functions:
An image type that can be displayed by the Image element
Error generated if an image cannot be loaded for any reasons.
Properties of type array in the .60 language are represented as
an Option
of an Rc
of something implemented the Model
trait
Dispatch notifications from a Model
to one or several ModelPeer
.
Typically, you would want to put this in the implementaiton of the Model
Represent a handle to a view that listens to changes to a model. See Model::attach_peer
and ModelNotify
RgbaColor stores the red, green, blue and alpha components of a color
with the precision of the generic parameter T. For example if T is f32,
the values are normalized between 0 and 1. If T is u8, they values range
is 0 to 255.
This is merely a helper class for use with Color
.
A string type used by the SixtyFPS run-time.
SharedVector holds a reference-counted read-only copy of [T]
.
Represend an item in a StandardListView
Timer is a handle to the timer system that allows triggering a callback to be called after a specified period of time.
A model backed by a SharedVector
Struct that’s used to hold weak references of SixtyFPS component
Enums
A brush is a data structure that is used to describe how a shape, such as a rectangle, path or even text, shall be filled. A brush can also be applied to the outline of a shape, that means the fill of the outline itself.
The TimerMode specifies what should happen after the timer fired.
Traits
This trait describes the common public API of a strongly referenced SixtyFPS component. It allows creating strongly-referenced clones, a conversion into/ a weak pointer as well as other convenience functions.
A Model is providing Data for the Repeater or ListView elements of the .60
language
Functions
Adds the specified function to an internal queue, notifies the event loop to wake up. Once woken up, any queued up functors will be invoked.
Schedules the main event loop for termination. This function is meant
to be called from callbacks triggered by the UI. After calling the function,
it will return immediately and once control is passed back to the event loop,
the initial call to run_event_loop()
will return.
Enters the main event loop. This is necessary in order to receive events from the windowing system in order to render to the screen and react to user input.