-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial States
Before we go on to describe the scheduler, we have to look at widget states first. We said that the scheduler was how we manage the UI from code, and we do that by manipulating widget states. Every property of a widget (such as those we set from the .ez files) is contained in its widget state. If we change a property in the widget state and call the '.update' method on it, the widget will be redrawn on the next frame to reflect the new state. So if we wanted to change the text of a label from code it would look like this:
label_state.set_text("new text".to_string());
The state of every widget active in our UI is contained in the "State tree". The state tree is available to us when we initialize the UI, and is given to us in every callback. We can use the state tree to get a widget state using the "get" or "get_mut" methods. So if we wanted to change the text of a label with the id "my_label" when initializing the UI, we would do this:
use ez_term::*;
let (root_widget, mut state_tree, mut scheduler) = load_ui();
let label_state = state_tree.get_mut("my_label").as_label_mut();
label_state.set_text("new text".to_string());
run(root_widget, state_tree, scheduler);
Note that after getting the state of the label, we have to call the "to_label_mut" method to change the state into a label state. This is because the state tree contains generic states (due to Rusts strict type requirements), and so we have to cast the state into the right type before we can actually use it. This will become second nature quickly when working with EzTerm. Just keep in mind: if you want to actually alter the property of a state, call "to_x" or "to_x_mut" on it first. Here are all available casts:
- as_layout(_mut)
- as_label(_mut)
- as_text_input(_mut)
- as_button(_mut)
- as_checkbox(_mut)
- as_radio_button(_mut)
- as_slider(_mut)
- as_dropdown(_mut)
- as_progress_bar(_mut)
- as_canvas(_mut)
The 'state_tree' object is actually the root layout state. So if you ever need the root layout state, you would get it like this:
let root_layout_state = state_tree.as_layout();
If we want any other states, we have to use the "get" or "get_mut" methods to find them. In the earlier example we used a widget ID for this. There are in fact three ways to find states in the state tree: by ID, by path or by chaining 'get' calls. Let's look at examples of all three methods:
By id:
let label_state = state_tree.get("my_label").as_label();
Important note: to find widgets by ID, the ID must be unique from that point in the tree. That means that if you search an ID from the root of the state tree, that the ID must be globally unique! As a general rule, make all IDs in your .ez files globally unique if at all possible, because finding states by ID is the most comfortable way to do it, and incurs no performance penalty due to caching.
By path:
let label_state = state_tree.get("/root/layout/sub_layout/my_label").as_label();
Here we used the full path to find a widget. A true full path always starts with "/root" (the static name of the root layout), but since "state_tree" is in fact the root itself, we do not necessarily have to start our paths with "/root", so we could use the shorter version:
let label_state = state_tree.get("/layout/sub_layout/my_label").as_label();
This is still a bit verbose, so it's usually more convenient to make IDs globally unique and search by ID.
By chaining get calls:
The last method is to chain get calls. The 'get' method returns another part of the state tree, so we could just call 'get' again:
let label_state = state_tree.get("layout").get("sub_layout").get("my_label").as_label();
This is very verbose; so when is this useful? Mostly you want to avoid it, but it comes in handy when you want to manipulate multiple child states with non-unique IDs. Let's say you have layouts with three labels, and you want to update the text of each label. You could retrieve the layout state first, and then access each child state from there:
let layout_1 = state_tree.get("sub_layout_1");
layout_1.get("my_label_1").as_label_mut().set_text("Some".to_string());
layout_1.get("my_label_2").as_label_mut().set_text("new".to_string());
layout_1.get("my_label_3").as_label_mut().set_text("Text".to_string());
let layout_2 = state_tree.get("sub_layout_2");
layout_2.get("my_label_1").as_label_mut().set_text("Some".to_string());
layout_2.get("my_label_2").as_label_mut().set_text("new".to_string());
layout_2.get("my_label_3").as_label_mut().set_text("Text".to_string());
We will describe callbacks in their own page, but we will note for now that the state tree is available in callbacks through the "context" parameter. So if we wanted to change the text of our label from a callback it would look like this:
use ez_term::*;
fn my_callback(context: Context) -> bool {
let label_state = context.state_tree.get_mut("my_label").as_label_mut();
label_state.set_text("new text".to_string());
label_state.update(context.scheduler);
true
}
Don't worry about the callback syntax for now, just note that we control widgets from code by manipulating the state, which we get from the state tree available in the callback context. We could also see in the example that each state has an ".update" method. When we call update, the widget will be redrawn on the next frame. You will want to call this when changing a state from a callback most of the time.
Now we'll look at the scheduler object. After that, we will start putting our new knowledge about states to use when discussing the actual features of the scheduler.
The general tutorial continues with: The Scheduler Object.
Tutorial
Tutorial-Project-StructureMinimal example
EzLang
EzLang basics
EzLang Templates
Ezlang Layout modes
EzLang Box mode layouts
EzLang Stack mode layouts
EzLang Table mode layouts
EzLang Float mode layouts
EzLang Tab mode layouts
EzLang Screen mode layouts
EzLang Layout Scrolling
EzLang Layout Views
EzLang Widget overview
EzLang Label
EzLang Text Input
EzLang Button
EzLang Checkbox
EzLang Radio button
EzLang Dropdown
EzLang Slider
EzLang Canvas
EzLang Property Binding
EzLang Sizing
EzLang Size hints
EzLang Auto scaling
EzLang Maths Sizing
EzLang Manual Sizing
EzLang Positioning
EzLang Layout Mode Positioning
EzLang Position Hints
EzLang Position Maths
EzLang Manual Position
EzLang Adjusting Position
EzLang Keyboard Selection
Scheduler
Widget States and the State Tree
The Scheduler Object
Managing callbacks
Callback Structure
Callback Configs
Callback: On keyboard enter
Callback: On Left Mouse Click
Callback: On Press
Callback: On Select
Callback: On Deselect
Callback: On Right Mouse Click
Callback: On Hover
Callback: On Drag
Callback: On Scroll Up
Callback: On Scroll Down
Callback: On Value Change
Callback: Custom Key Binds
Callback: Global Key Binds
Callback: Property Binds
Tasks
Scheduled Single Exectution Tasks
Scheduled Recurring Tasks
Threaded Tasks
Custom Properties
Modals
Programmatic Widgets
Updating widgets
Managing selection
Default global (key)binds
Performance
Examples
Layout: Box Mode NestedLayout: Box Mode Size Hints
Layout: Stack Mode
Layout: Table Mode Dynamic
Layout: Table Mode Static
Layout: Float Mode Manual
Layout: Float Mode Position hints
Layout: Screen Mode
Layout: Tab Mode
Layout: Scrolling
Layout: Views
Widget: Label
Widget: Text input
Widget: Button
Widget: Checkbox
Widget: Radio Button
Widget: Dropdown
Widget: Slider
Widget: Progress Bar
Widget: Canvas
Scheduler: Schedule Once
Scheduler: Schedule Once Callback
Scheduler: Schedule Recurring
Scheduler: Schedule Recurring Callback
Scheduler: Threaded Task State Tree
Scheduler: Threaded Task Custom Property
Scheduler: Create Widgets
Scheduler: Modal Popup
Reference
WidgetsCommon Properties
Label
Text Input
Button
Checkbox
Radio button
Dropdown
Slider
Canvas
Scheduler
Schedule once
Schedule Recurring
Schedule Threaded
Cancel Task
Cancel Recurring Task
Create Widget
Remove Widget
Select Widget
Deselect Widget
Update Widget
Force Redraw
Open Modal
Dismiss Modal
Bind Global Key
Remove Global Key
Clear Global Keys
Bind Property
Create Custom Properties
Get Property
Get Property Mut
Overwrite Callback Config
Update Callback Config
Exit