Struct oxygengine_user_interface::raui::core::application::Application
source · pub struct Application {
pub animations_delta_time: f32,
/* private fields */
}
Expand description
Contains and orchestrates application layout, animations, interactions, etc.
See the application
module for more information and examples.
Fields§
§animations_delta_time: f32
The amount of time between the last update, used when calculating animation progress
Implementations§
source§impl Application
impl Application
pub fn new() -> Application
sourcepub fn setup<F>(&mut self, f: F)where
F: FnMut(&mut Application),
pub fn setup<F>(&mut self, f: F)where F: FnMut(&mut Application),
Setup the application with a given a setup function
We need to run the setup
function for the application to register components and
properties if we want to support serialization of the UI. We pass it a function that will do
the actual registration.
Note: RAUI will work fine without running any
setup
if UI serialization is not required.
Example
application.setup(setup /* the core setup function from the RAUI prelude */);
If you use crates like the raui_material
crate you will want to call it’s setup function
as well.
application.setup(raui_material::setup);
sourcepub fn change_notifier(&self) -> ChangeNotifier
pub fn change_notifier(&self) -> ChangeNotifier
Get the ChangeNotifier
for the Application
Having the ChangeNotifier
allows you to check whether the application has changed and
allows you to force application updates by marking the app as changed.
ChangeNotifier
s are also used to create data bindingss.
sourcepub fn register_component(
&mut self,
type_name: &str,
processor: fn(_: WidgetContext<'_, '_>) -> WidgetNode
)
pub fn register_component( &mut self, type_name: &str, processor: fn(_: WidgetContext<'_, '_>) -> WidgetNode )
Register’s a component under a string name used when serializing the UI
This function is often used in setup
functions for registering batches of
components.
Example
fn my_widget(ctx: WidgetContext) -> WidgetNode {
todo!("make awesome widget");
}
fn setup_widgets(app: &mut Application) {
app.register_component("my_widget", my_widget);
}
let mut application = Application::new();
application.setup(setup_widgets);
sourcepub fn unregister_component(&mut self, type_name: &str)
pub fn unregister_component(&mut self, type_name: &str)
Unregisters a component
sourcepub fn register_props<T>(&mut self, name: &str)where
T: 'static + Prefab + PropsData,
pub fn register_props<T>(&mut self, name: &str)where T: 'static + Prefab + PropsData,
Register’s a property type under a string name used when serializing the UI
This function is often used in setup
functions for registering batches of
properties.
Example
#[derive(PropsData, Debug, Default, Copy, Clone, Serialize, Deserialize)]
struct MyProp {
awesome: bool,
}
fn setup_properties(app: &mut Application) {
app.register_props::<MyProp>("MyProp");
}
let mut application = Application::new();
application.setup(setup_properties);
sourcepub fn unregister_props(&mut self, name: &str)
pub fn unregister_props(&mut self, name: &str)
Unregisters a property type
See register_props
sourcepub fn serialize_props(&self, props: &Props) -> Result<Value, PrefabError>
pub fn serialize_props(&self, props: &Props) -> Result<Value, PrefabError>
Serialize the given Props
to a PrefabValue
sourcepub fn deserialize_props(&self, data: Value) -> Result<Props, PrefabError>
pub fn deserialize_props(&self, data: Value) -> Result<Props, PrefabError>
Deserialize Props
from a PrefabValue
sourcepub fn serialize_node(
&self,
data: &WidgetNode
) -> Result<Value, ApplicationError>
pub fn serialize_node( &self, data: &WidgetNode ) -> Result<Value, ApplicationError>
Serialize a WidgetNode
to a PrefabValue
sourcepub fn deserialize_node(
&self,
data: Value
) -> Result<WidgetNode, ApplicationError>
pub fn deserialize_node( &self, data: Value ) -> Result<WidgetNode, ApplicationError>
Deserialize a WidgetNode
from a PrefabValue
sourcepub fn last_invalidation_cause(&self) -> &InvalidationCause
pub fn last_invalidation_cause(&self) -> &InvalidationCause
Get the reason that the application state was last invalidated and caused to re-process
sourcepub fn mark_dirty(&mut self)
pub fn mark_dirty(&mut self)
Force mark the application as needing to re-process
pub fn does_render_changed(&self) -> bool
sourcepub fn tree(&self) -> &WidgetNode
pub fn tree(&self) -> &WidgetNode
Get the WidgetNode
for the application tree
sourcepub fn rendered_tree(&self) -> &WidgetUnit
pub fn rendered_tree(&self) -> &WidgetUnit
Get the application widget tree rendered to raw WidgetUnit
’s
sourcepub fn layout_data(&self) -> &Layout
pub fn layout_data(&self) -> &Layout
Get the application Layout
data
pub fn has_layout_widget(&self, id: &WidgetId) -> bool
sourcepub fn apply(&mut self, tree: WidgetNode)
pub fn apply(&mut self, tree: WidgetNode)
Update the application widget tree
sourcepub fn render<R, T, E>(
&self,
mapping: &CoordsMapping,
renderer: &mut R
) -> Result<T, E>where
R: Renderer<T, E>,
pub fn render<R, T, E>( &self, mapping: &CoordsMapping, renderer: &mut R ) -> Result<T, E>where R: Renderer<T, E>,
Render the application
sourcepub fn render_change<R, T, E>(
&mut self,
mapping: &CoordsMapping,
renderer: &mut R
) -> Result<Option<T>, E>where
R: Renderer<T, E>,
pub fn render_change<R, T, E>( &mut self, mapping: &CoordsMapping, renderer: &mut R ) -> Result<Option<T>, E>where R: Renderer<T, E>,
Render the application, but only if something effecting the rendering has changed and it needs to be re-rendered
sourcepub fn layout<L, E>(
&mut self,
mapping: &CoordsMapping,
layout_engine: &mut L
) -> Result<(), E>where
L: LayoutEngine<E>,
pub fn layout<L, E>( &mut self, mapping: &CoordsMapping, layout_engine: &mut L ) -> Result<(), E>where L: LayoutEngine<E>,
Calculate application layout
sourcepub fn layout_change<L, E>(
&mut self,
mapping: &CoordsMapping,
layout_engine: &mut L
) -> Result<bool, E>where
L: LayoutEngine<E>,
pub fn layout_change<L, E>( &mut self, mapping: &CoordsMapping, layout_engine: &mut L ) -> Result<bool, E>where L: LayoutEngine<E>,
Calculate application layout, but only if something effecting application layout has changed and the layout needs to be re-done
sourcepub fn interact<I, R, E>(&mut self, interactions_engine: &mut I) -> Result<R, E>where
I: InteractionsEngine<R, E>,
pub fn interact<I, R, E>(&mut self, interactions_engine: &mut I) -> Result<R, E>where I: InteractionsEngine<R, E>,
Perform interactions on the application using the given interaction engine
sourcepub fn send_message<T>(&mut self, id: &WidgetId, data: T)where
T: 'static + MessageData,
pub fn send_message<T>(&mut self, id: &WidgetId, data: T)where T: 'static + MessageData,
Send a message to the given widget
sourcepub fn send_message_raw(
&mut self,
id: &WidgetId,
data: Box<dyn MessageData, Global>
)
pub fn send_message_raw( &mut self, id: &WidgetId, data: Box<dyn MessageData, Global> )
Send raw message data to the given widget
sourcepub fn signals(&self) -> &[(WidgetId, Box<dyn MessageData, Global>)]
pub fn signals(&self) -> &[(WidgetId, Box<dyn MessageData, Global>)]
Get the list of signals that have been sent by widgets
sourcepub fn consume_signals(
&mut self
) -> Vec<(WidgetId, Box<dyn MessageData, Global>), Global>
pub fn consume_signals( &mut self ) -> Vec<(WidgetId, Box<dyn MessageData, Global>), Global>
Get the list of signals that have been sent by widgets, consuming the current list so that further calls will not include previously sent signals
sourcepub fn state_write(&mut self, id: &WidgetId, data: Props)
pub fn state_write(&mut self, id: &WidgetId, data: Props)
Set the props of a given widget
sourcepub fn state_mutate<F>(&mut self, id: &WidgetId, f: F)where
F: FnMut(&Props) -> Props,
pub fn state_mutate<F>(&mut self, id: &WidgetId, f: F)where F: FnMut(&Props) -> Props,
Get read access to the given widget’s Props
in a closure and update the widget’s props
to the props that were returned by the closure
sourcepub fn state_mutate_cloned<F>(&mut self, id: &WidgetId, f: F)where
F: FnMut(&mut Props),
pub fn state_mutate_cloned<F>(&mut self, id: &WidgetId, f: F)where F: FnMut(&mut Props),
Get mutable access to the cloned Props
of a widget in a closure and update the widget’s
props to the value of the clone props after the closure modifies them
sourcepub fn forced_process(&mut self) -> bool
pub fn forced_process(&mut self) -> bool
process()
application, even if no changes have been detected
sourcepub fn forced_process_with_context<'b>(
&mut self,
process_context: &mut ProcessContext<'b>
) -> bool
pub fn forced_process_with_context<'b>( &mut self, process_context: &mut ProcessContext<'b> ) -> bool
process()
application, even if no changes have been detected
sourcepub fn process(&mut self) -> bool
pub fn process(&mut self) -> bool
Process the application, updating animations, applying state changes, handling widget messages, etc.
sourcepub fn process_with_context<'a>(
&mut self,
process_context: &mut ProcessContext<'a>
) -> bool
pub fn process_with_context<'a>( &mut self, process_context: &mut ProcessContext<'a> ) -> bool
Process the application and provide a custom ProcessContext
Process Context
The process_context
argument allows you to provide the UI’s components with mutable or
immutable access to application data. This grants powerful, direct control over the
application to the UI’s widgets, but has some caveats and it is easy to fall into
anti-patterns when using.
You should consider carefully whether or not a process context is the best way to facilitate your use-case before using this feature. See caveats below for more explanation.
Caveats
RAUI provides other ways to facilitate UI integration with external data that should generally be preferred over using a process context. The primary mechanisms are:
DataBinding
s and widget messages, for having the application send data to widgets- signals for having widgets send data to the application.
The main difference between using a DataBinding
and a process context is the fact that
RAUI is able to more granularly update the widget tree in response to data changes when
using DataBinding
, but it has no way to know know when data in a process context
changes.
When you use a process context you are now responsible for either running
forced_process_with_context
every frame to make sure
that the UI is always updated when the process context changes, or by manually calling
mark_dirty
when the process context has changed to make sure that the
next process_with_context()
call will actually update the application.
Example
/// Some sort of application data
///
/// Pretend this data cannot be cloned because it has some special requirements.
struct AppData {
counter: i32
}
// Make our data
let mut app_data = AppData {
counter: 0,
};
let mut app = Application::new();
// Do application stuff like interactions, layout, etc...
// Now when it is time to process our application we create a process context and we put
// a _mutable reference_ to our app data in the context. This means we don't have to have
// ownership of our `AppData` struct, which is useful when the UI event loop doesn't
// own the data it needs access to.
// Now we call `process` with our process context
app.process_with_context(ProcessContext::new().insert_mut(&mut app_data));
Now, in our components we can access the AppData
through the widget’s WidgetContext
fn my_component(ctx: WidgetContext) -> WidgetNode {
let app_data = ctx.process_context.get_mut::<AppData>().unwrap();
let counter = &mut app_data.counter;
*counter += 1;
// widget stuff...
}