Compare commits
5 commits
95b66db697
...
87893d2973
Author | SHA1 | Date | |
---|---|---|---|
87893d2973 | |||
d4997dff39 | |||
|
22994c97f6 | ||
|
c8b0c46d0e | ||
|
b09ec887ab |
14 changed files with 234 additions and 184 deletions
|
@ -5,7 +5,7 @@ authors = ["hodasemi <michaelh.95@t-online.de>"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quick-xml = "0.31.0"
|
quick-xml = "0.37.0"
|
||||||
serde = { version = "1.0.203", features = ["derive"] }
|
serde = { version = "1.0.203", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.120" }
|
serde_json = { version = "1.0.120" }
|
||||||
paste = "1.0.15"
|
paste = "1.0.15"
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{Context, Result, bail};
|
||||||
|
|
||||||
use assetpath::AssetPath;
|
use assetpath::AssetPath;
|
||||||
|
|
||||||
use super::validator::buttoninfo::{NeighbourDirection, NeighbourInfo};
|
use super::validator::buttoninfo::{NeighbourDirection, NeighbourInfo};
|
||||||
use super::validator::gridinfo::GridInfo;
|
use super::validator::gridinfo::GridInfo;
|
||||||
use super::validator::uiinfoelement::UiInfoElement;
|
use super::validator::uiinfoelement::UiInfoElement;
|
||||||
use super::validator::validator::{handle_function_suffix, Validator};
|
use super::validator::validator::{Validator, handle_function_suffix};
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -22,7 +22,7 @@ pub struct GuiBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuiBuilder {
|
impl GuiBuilder {
|
||||||
pub fn new(gui_handler: &Arc<GuiHandler>, path: &AssetPath) -> Result<Arc<Self>> {
|
pub fn new(gui_handler: &mut GuiHandler, path: &AssetPath) -> Result<Arc<Self>> {
|
||||||
let validator = Validator::new(
|
let validator = Validator::new(
|
||||||
#[cfg(feature = "audio")]
|
#[cfg(feature = "audio")]
|
||||||
gui_handler,
|
gui_handler,
|
||||||
|
@ -35,7 +35,7 @@ impl GuiBuilder {
|
||||||
)?))
|
)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_str(gui_handler: &Arc<GuiHandler>, s: &str) -> Result<Arc<Self>> {
|
pub fn from_str(gui_handler: &mut GuiHandler, s: &str) -> Result<Arc<Self>> {
|
||||||
let validator = Validator::from_str(
|
let validator = Validator::from_str(
|
||||||
#[cfg(feature = "audio")]
|
#[cfg(feature = "audio")]
|
||||||
gui_handler,
|
gui_handler,
|
||||||
|
@ -46,7 +46,7 @@ impl GuiBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merge<'a>(
|
pub fn merge<'a>(
|
||||||
gui_handler: &Arc<GuiHandler>,
|
gui_handler: &mut GuiHandler,
|
||||||
pathes: impl IntoIterator<Item = &'a AssetPath>,
|
pathes: impl IntoIterator<Item = &'a AssetPath>,
|
||||||
) -> Result<Arc<Self>> {
|
) -> Result<Arc<Self>> {
|
||||||
let mut me = Self {
|
let mut me = Self {
|
||||||
|
@ -85,7 +85,7 @@ impl GuiBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn _new(gui_handler: &Arc<GuiHandler>, validator: Validator) -> Result<Self> {
|
fn _new(gui_handler: &mut GuiHandler, validator: Validator) -> Result<Self> {
|
||||||
let root = validator.root();
|
let root = validator.root();
|
||||||
|
|
||||||
let mut ids = HashMap::new();
|
let mut ids = HashMap::new();
|
||||||
|
@ -178,7 +178,10 @@ impl GuiBuilder {
|
||||||
impl Functionality for GuiBuilder {
|
impl Functionality for GuiBuilder {
|
||||||
fn set_click_callbacks(
|
fn set_click_callbacks(
|
||||||
&self,
|
&self,
|
||||||
functions: Vec<(&str, Box<dyn Fn() -> Result<()> + Send + Sync>)>,
|
functions: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (function_name, callback) in functions {
|
for (function_name, callback) in functions {
|
||||||
let suffix_less_function_name = handle_function_suffix(function_name);
|
let suffix_less_function_name = handle_function_suffix(function_name);
|
||||||
|
@ -235,9 +238,9 @@ impl Visibility for GuiBuilder {
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_visibility(&self, visibility: bool) -> Result<()> {
|
fn set_visibility(&self, gui_handler: &mut GuiHandler, visibility: bool) -> Result<()> {
|
||||||
for grid in &self.grids {
|
for grid in &self.grids {
|
||||||
grid.set_visibility(visibility)?;
|
grid.set_visibility(gui_handler, visibility)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -259,7 +262,7 @@ impl GuiElementTraits for GuiBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopGui for GuiBuilder {
|
impl TopGui for GuiBuilder {
|
||||||
fn decline(&self) -> Result<()> {
|
fn decline(&self, _gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
if let Some(decline_callback) = self.decline_callback.read().unwrap().as_ref() {
|
if let Some(decline_callback) = self.decline_callback.read().unwrap().as_ref() {
|
||||||
decline_callback()?;
|
decline_callback()?;
|
||||||
}
|
}
|
||||||
|
@ -267,11 +270,11 @@ impl TopGui for GuiBuilder {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_tab(&self, _: bool) -> Result<()> {
|
fn next_tab(&self, _gui_handler: &mut GuiHandler, _: bool) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn previous_tab(&self, _: bool) -> Result<()> {
|
fn previous_tab(&self, _gui_handler: &mut GuiHandler, _: bool) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,18 +296,18 @@ impl TopLevelGui for GuiBuilder {
|
||||||
Some(self)
|
Some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(&self) -> Result<()> {
|
fn enable(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
self.set_visibility(true)?;
|
self.set_visibility(gui_handler, true)?;
|
||||||
|
|
||||||
if let Some(button) = &self.default_select {
|
if let Some(button) = &self.default_select {
|
||||||
Button::select(button)?;
|
button.select(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable(&self) -> Result<()> {
|
fn disable(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
self.set_visibility(false)?;
|
self.set_visibility(gui_handler, false)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -332,7 +335,7 @@ impl_element!(MultiLineTextField);
|
||||||
// private
|
// private
|
||||||
impl GuiBuilder {
|
impl GuiBuilder {
|
||||||
fn create_tree(
|
fn create_tree(
|
||||||
gui_handler: &Arc<GuiHandler>,
|
gui_handler: &mut GuiHandler,
|
||||||
ids: &mut HashMap<String, UiElement>,
|
ids: &mut HashMap<String, UiElement>,
|
||||||
root_grid_info: &Arc<GridInfo>,
|
root_grid_info: &Arc<GridInfo>,
|
||||||
default_button: &mut Option<Arc<Button>>,
|
default_button: &mut Option<Arc<Button>>,
|
||||||
|
@ -340,7 +343,7 @@ impl GuiBuilder {
|
||||||
(reference_width, reference_height): (Option<u32>, Option<u32>),
|
(reference_width, reference_height): (Option<u32>, Option<u32>),
|
||||||
layer: i32,
|
layer: i32,
|
||||||
) -> Result<Arc<Grid>> {
|
) -> Result<Arc<Grid>> {
|
||||||
let root_grid = Grid::try_from(root_grid_info, gui_handler, true)?;
|
let root_grid = Grid::try_from(gui_handler, root_grid_info, true)?;
|
||||||
let root_layer = root_grid_info.layer.unwrap_or(layer);
|
let root_layer = root_grid_info.layer.unwrap_or(layer);
|
||||||
root_grid.set_layer(root_layer)?;
|
root_grid.set_layer(root_layer)?;
|
||||||
|
|
||||||
|
@ -348,11 +351,12 @@ impl GuiBuilder {
|
||||||
if let Some(ref_height) = reference_height {
|
if let Some(ref_height) = reference_height {
|
||||||
root_grid
|
root_grid
|
||||||
.framable
|
.framable
|
||||||
.set_reference_size(ref_width, ref_height)?;
|
.set_reference_size(gui_handler, ref_width, ref_height)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
root_grid.set_frame(
|
root_grid.set_frame(
|
||||||
|
gui_handler,
|
||||||
root_grid_info
|
root_grid_info
|
||||||
.x_offset
|
.x_offset
|
||||||
.get()
|
.get()
|
||||||
|
@ -397,7 +401,7 @@ impl GuiBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_child(
|
fn create_child(
|
||||||
gui_handler: &Arc<GuiHandler>,
|
gui_handler: &mut GuiHandler,
|
||||||
child: &UiInfoElement,
|
child: &UiInfoElement,
|
||||||
grid: &Grid,
|
grid: &Grid,
|
||||||
ids: &mut HashMap<String, UiElement>,
|
ids: &mut HashMap<String, UiElement>,
|
||||||
|
@ -407,11 +411,12 @@ impl GuiBuilder {
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match child {
|
match child {
|
||||||
UiInfoElement::Button(button_info) => {
|
UiInfoElement::Button(button_info) => {
|
||||||
let button = Button::try_from(button_info, gui_handler)?;
|
let button = Button::try_from(gui_handler, button_info)?;
|
||||||
|
|
||||||
Self::insert_id(ids, &button_info.id, &button)?;
|
Self::insert_id(ids, &button_info.id, &button)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
button.clone(),
|
button.clone(),
|
||||||
button_info
|
button_info
|
||||||
.x_slot
|
.x_slot
|
||||||
|
@ -434,7 +439,7 @@ impl GuiBuilder {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
return Err(anyhow::Error::msg(
|
return Err(anyhow::Error::msg(
|
||||||
"It is not allowed to select multiple UI elements",
|
"It is not allowed to select multiple UI elements",
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
None => *default_button = Some(button.clone()),
|
None => *default_button = Some(button.clone()),
|
||||||
}
|
}
|
||||||
|
@ -446,6 +451,7 @@ impl GuiBuilder {
|
||||||
Self::insert_id(ids, &label_info.id, &label)?;
|
Self::insert_id(ids, &label_info.id, &label)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
label.clone(),
|
label.clone(),
|
||||||
label_info.x_slot.get().with_context(|| "x_slot of label")?,
|
label_info.x_slot.get().with_context(|| "x_slot of label")?,
|
||||||
label_info.y_slot.get().with_context(|| "y_slot of label")?,
|
label_info.y_slot.get().with_context(|| "y_slot of label")?,
|
||||||
|
@ -462,6 +468,7 @@ impl GuiBuilder {
|
||||||
GuiBuilder::insert_id(ids, &multi_line_label_info.id, &multi_line_label)?;
|
GuiBuilder::insert_id(ids, &multi_line_label_info.id, &multi_line_label)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
multi_line_label.clone(),
|
multi_line_label.clone(),
|
||||||
multi_line_label_info
|
multi_line_label_info
|
||||||
.x_slot
|
.x_slot
|
||||||
|
@ -484,6 +491,7 @@ impl GuiBuilder {
|
||||||
GuiBuilder::insert_id(ids, &multi_line_text_field_info.id, &multi_line_text_field)?;
|
GuiBuilder::insert_id(ids, &multi_line_text_field_info.id, &multi_line_text_field)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
multi_line_text_field.clone(),
|
multi_line_text_field.clone(),
|
||||||
multi_line_text_field_info
|
multi_line_text_field_info
|
||||||
.x_slot
|
.x_slot
|
||||||
|
@ -505,6 +513,7 @@ impl GuiBuilder {
|
||||||
Self::insert_id(ids, &text_field_info.id, &text_field)?;
|
Self::insert_id(ids, &text_field_info.id, &text_field)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
text_field.clone(),
|
text_field.clone(),
|
||||||
text_field_info
|
text_field_info
|
||||||
.x_slot
|
.x_slot
|
||||||
|
@ -526,6 +535,7 @@ impl GuiBuilder {
|
||||||
Self::insert_id(ids, &icon_info.id, UiElement::Icon(Arc::downgrade(&icon)))?;
|
Self::insert_id(ids, &icon_info.id, UiElement::Icon(Arc::downgrade(&icon)))?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
icon.clone(),
|
icon.clone(),
|
||||||
icon_info.x_slot.get().with_context(|| "x_slot of icon")?,
|
icon_info.x_slot.get().with_context(|| "x_slot of icon")?,
|
||||||
icon_info.y_slot.get().with_context(|| "y_slot of icon")?,
|
icon_info.y_slot.get().with_context(|| "y_slot of icon")?,
|
||||||
|
@ -541,6 +551,7 @@ impl GuiBuilder {
|
||||||
Self::insert_id(ids, &progress_bar_info.id, &progress_bar)?;
|
Self::insert_id(ids, &progress_bar_info.id, &progress_bar)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
progress_bar.clone(),
|
progress_bar.clone(),
|
||||||
progress_bar_info
|
progress_bar_info
|
||||||
.x_slot
|
.x_slot
|
||||||
|
@ -557,11 +568,12 @@ impl GuiBuilder {
|
||||||
progress_bar.set_layer(layer)?;
|
progress_bar.set_layer(layer)?;
|
||||||
}
|
}
|
||||||
UiInfoElement::Grid(grid_info) => {
|
UiInfoElement::Grid(grid_info) => {
|
||||||
let sub_grid = Grid::try_from(grid_info, gui_handler, false)?;
|
let sub_grid = Grid::try_from(gui_handler, grid_info, false)?;
|
||||||
|
|
||||||
Self::insert_id(ids, &grid_info.id, &sub_grid)?;
|
Self::insert_id(ids, &grid_info.id, &sub_grid)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
sub_grid.clone(),
|
sub_grid.clone(),
|
||||||
grid_info.x_slot.get().with_context(|| "x_slot of grid")?,
|
grid_info.x_slot.get().with_context(|| "x_slot of grid")?,
|
||||||
grid_info.y_slot.get().with_context(|| "y_slot of grid")?,
|
grid_info.y_slot.get().with_context(|| "y_slot of grid")?,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use assetpath::AssetPath;
|
||||||
use super::validator::{
|
use super::validator::{
|
||||||
buttoninfo::NeighbourInfo,
|
buttoninfo::NeighbourInfo,
|
||||||
uiinfoelement::UiInfoElement,
|
uiinfoelement::UiInfoElement,
|
||||||
validator::{handle_function_suffix, Validator},
|
validator::{Validator, handle_function_suffix},
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
@ -17,17 +17,17 @@ pub struct GuiSnippet {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuiSnippet {
|
impl GuiSnippet {
|
||||||
pub fn new(gui_handler: &Arc<GuiHandler>, path: &AssetPath) -> Result<Arc<Self>> {
|
pub fn new(gui_handler: &mut GuiHandler, path: &AssetPath) -> Result<Arc<Self>> {
|
||||||
let validator = Validator::new(
|
let validator = Validator::new(
|
||||||
#[cfg(feature = "audio")]
|
#[cfg(feature = "audio")]
|
||||||
&gui_handler,
|
gui_handler,
|
||||||
path,
|
path,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Self::_new(gui_handler, validator)
|
Self::_new(gui_handler, validator)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_str(gui_handler: &Arc<GuiHandler>, s: &str) -> Result<Arc<Self>> {
|
pub fn from_str(gui_handler: &mut GuiHandler, s: &str) -> Result<Arc<Self>> {
|
||||||
let validator = Validator::from_str(
|
let validator = Validator::from_str(
|
||||||
#[cfg(feature = "audio")]
|
#[cfg(feature = "audio")]
|
||||||
gui_handler,
|
gui_handler,
|
||||||
|
@ -37,7 +37,7 @@ impl GuiSnippet {
|
||||||
Self::_new(gui_handler, validator)
|
Self::_new(gui_handler, validator)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _new(gui_handler: &Arc<GuiHandler>, validator: Validator) -> Result<Arc<Self>> {
|
fn _new(gui_handler: &mut GuiHandler, validator: Validator) -> Result<Arc<Self>> {
|
||||||
let root = validator.root();
|
let root = validator.root();
|
||||||
|
|
||||||
let mut ids = HashMap::new();
|
let mut ids = HashMap::new();
|
||||||
|
@ -51,12 +51,12 @@ impl GuiSnippet {
|
||||||
}
|
}
|
||||||
|
|
||||||
let grid_info = &root.children[0];
|
let grid_info = &root.children[0];
|
||||||
let grid = Grid::try_from(grid_info, &gui_handler, false)?;
|
let grid = Grid::try_from(gui_handler, grid_info, false)?;
|
||||||
|
|
||||||
GuiBuilder::insert_id(&mut ids, &grid_info.id, &grid)?;
|
GuiBuilder::insert_id(&mut ids, &grid_info.id, &grid)?;
|
||||||
|
|
||||||
for child in grid_info.children.read().unwrap().iter() {
|
for child in grid_info.children.read().unwrap().iter() {
|
||||||
Self::create_child(&gui_handler, child, &grid, &mut ids, &mut custom_neighbours)?;
|
Self::create_child(gui_handler, child, &grid, &mut ids, &mut custom_neighbours)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiBuilder::connect_custom_neighbours(&ids, custom_neighbours)?;
|
GuiBuilder::connect_custom_neighbours(&ids, custom_neighbours)?;
|
||||||
|
@ -93,8 +93,8 @@ impl Visibility for GuiSnippet {
|
||||||
self.grid.visible()
|
self.grid.visible()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_visibility(&self, visibility: bool) -> Result<()> {
|
fn set_visibility(&self, gui_handler: &mut GuiHandler, visibility: bool) -> Result<()> {
|
||||||
self.grid.set_visibility(visibility)
|
self.grid.set_visibility(gui_handler, visibility)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +115,7 @@ impl GuiElementTraits for GuiSnippet {
|
||||||
impl Gridable for GuiSnippet {
|
impl Gridable for GuiSnippet {
|
||||||
fn set_frame(
|
fn set_frame(
|
||||||
&self,
|
&self,
|
||||||
|
gui_handler: &mut GuiHandler,
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
w: u32,
|
w: u32,
|
||||||
|
@ -122,7 +123,8 @@ impl Gridable for GuiSnippet {
|
||||||
vert_align: VerticalAlign,
|
vert_align: VerticalAlign,
|
||||||
hori_align: HorizontalAlign,
|
hori_align: HorizontalAlign,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.grid.set_frame(x, y, w, h, vert_align, hori_align)
|
self.grid
|
||||||
|
.set_frame(gui_handler, x, y, w, h, vert_align, hori_align)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selectable(&self) -> Option<&Arc<Selectable>> {
|
fn selectable(&self) -> Option<&Arc<Selectable>> {
|
||||||
|
@ -145,7 +147,10 @@ impl Gridable for GuiSnippet {
|
||||||
impl Functionality for GuiSnippet {
|
impl Functionality for GuiSnippet {
|
||||||
fn set_click_callbacks(
|
fn set_click_callbacks(
|
||||||
&self,
|
&self,
|
||||||
functions: Vec<(&str, Box<dyn Fn() -> Result<()> + Send + Sync>)>,
|
functions: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (function_name, callback) in functions {
|
for (function_name, callback) in functions {
|
||||||
let suffix_less_function_name = handle_function_suffix(function_name);
|
let suffix_less_function_name = handle_function_suffix(function_name);
|
||||||
|
@ -195,7 +200,7 @@ impl Functionality for GuiSnippet {
|
||||||
|
|
||||||
impl GuiSnippet {
|
impl GuiSnippet {
|
||||||
fn create_child(
|
fn create_child(
|
||||||
gui_handler: &Arc<GuiHandler>,
|
gui_handler: &mut GuiHandler,
|
||||||
child: &UiInfoElement,
|
child: &UiInfoElement,
|
||||||
grid: &Grid,
|
grid: &Grid,
|
||||||
ids: &mut HashMap<String, UiElement>,
|
ids: &mut HashMap<String, UiElement>,
|
||||||
|
@ -203,11 +208,12 @@ impl GuiSnippet {
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match child {
|
match child {
|
||||||
UiInfoElement::Button(button_info) => {
|
UiInfoElement::Button(button_info) => {
|
||||||
let button = Button::try_from(button_info, gui_handler)?;
|
let button = Button::try_from(gui_handler, button_info)?;
|
||||||
|
|
||||||
GuiBuilder::insert_id(ids, &button_info.id, &button)?;
|
GuiBuilder::insert_id(ids, &button_info.id, &button)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
button.clone(),
|
button.clone(),
|
||||||
button_info.x_slot.get()?,
|
button_info.x_slot.get()?,
|
||||||
button_info.y_slot.get()?,
|
button_info.y_slot.get()?,
|
||||||
|
@ -223,6 +229,7 @@ impl GuiSnippet {
|
||||||
GuiBuilder::insert_id(ids, &label_info.id, &label)?;
|
GuiBuilder::insert_id(ids, &label_info.id, &label)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
label,
|
label,
|
||||||
label_info.x_slot.get()?,
|
label_info.x_slot.get()?,
|
||||||
label_info.y_slot.get()?,
|
label_info.y_slot.get()?,
|
||||||
|
@ -237,6 +244,7 @@ impl GuiSnippet {
|
||||||
GuiBuilder::insert_id(ids, &multi_line_label_info.id, &multi_line_label)?;
|
GuiBuilder::insert_id(ids, &multi_line_label_info.id, &multi_line_label)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
multi_line_label,
|
multi_line_label,
|
||||||
multi_line_label_info.x_slot.get()?,
|
multi_line_label_info.x_slot.get()?,
|
||||||
multi_line_label_info.y_slot.get()?,
|
multi_line_label_info.y_slot.get()?,
|
||||||
|
@ -251,6 +259,7 @@ impl GuiSnippet {
|
||||||
GuiBuilder::insert_id(ids, &multi_line_text_field_info.id, &multi_line_text_field)?;
|
GuiBuilder::insert_id(ids, &multi_line_text_field_info.id, &multi_line_text_field)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
multi_line_text_field,
|
multi_line_text_field,
|
||||||
multi_line_text_field_info.x_slot.get()?,
|
multi_line_text_field_info.x_slot.get()?,
|
||||||
multi_line_text_field_info.y_slot.get()?,
|
multi_line_text_field_info.y_slot.get()?,
|
||||||
|
@ -264,6 +273,7 @@ impl GuiSnippet {
|
||||||
GuiBuilder::insert_id(ids, &text_field_info.id, &text_field)?;
|
GuiBuilder::insert_id(ids, &text_field_info.id, &text_field)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
text_field,
|
text_field,
|
||||||
text_field_info.x_slot.get()?,
|
text_field_info.x_slot.get()?,
|
||||||
text_field_info.y_slot.get()?,
|
text_field_info.y_slot.get()?,
|
||||||
|
@ -277,6 +287,7 @@ impl GuiSnippet {
|
||||||
GuiBuilder::insert_id(ids, &icon_info.id, UiElement::Icon(Arc::downgrade(&icon)))?;
|
GuiBuilder::insert_id(ids, &icon_info.id, UiElement::Icon(Arc::downgrade(&icon)))?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
icon,
|
icon,
|
||||||
icon_info.x_slot.get()?,
|
icon_info.x_slot.get()?,
|
||||||
icon_info.y_slot.get()?,
|
icon_info.y_slot.get()?,
|
||||||
|
@ -290,6 +301,7 @@ impl GuiSnippet {
|
||||||
GuiBuilder::insert_id(ids, &progress_bar_info.id, &progress_bar)?;
|
GuiBuilder::insert_id(ids, &progress_bar_info.id, &progress_bar)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
progress_bar,
|
progress_bar,
|
||||||
progress_bar_info.x_slot.get()?,
|
progress_bar_info.x_slot.get()?,
|
||||||
progress_bar_info.y_slot.get()?,
|
progress_bar_info.y_slot.get()?,
|
||||||
|
@ -298,11 +310,12 @@ impl GuiSnippet {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
UiInfoElement::Grid(grid_info) => {
|
UiInfoElement::Grid(grid_info) => {
|
||||||
let sub_grid = Grid::try_from(grid_info, gui_handler, false)?;
|
let sub_grid = Grid::try_from(gui_handler, grid_info, false)?;
|
||||||
|
|
||||||
GuiBuilder::insert_id(ids, &grid_info.id, &sub_grid)?;
|
GuiBuilder::insert_id(ids, &grid_info.id, &sub_grid)?;
|
||||||
|
|
||||||
grid.attach(
|
grid.attach(
|
||||||
|
gui_handler,
|
||||||
sub_grid.clone(),
|
sub_grid.clone(),
|
||||||
grid_info.x_slot.get()?,
|
grid_info.x_slot.get()?,
|
||||||
grid_info.y_slot.get()?,
|
grid_info.y_slot.get()?,
|
||||||
|
|
|
@ -80,7 +80,7 @@ pub struct ButtonInfo {
|
||||||
|
|
||||||
impl ButtonInfo {
|
impl ButtonInfo {
|
||||||
pub fn new<'a>(
|
pub fn new<'a>(
|
||||||
#[cfg(feature = "audio")] gui_handler: &Arc<GuiHandler>,
|
#[cfg(feature = "audio")] gui_handler: &GuiHandler,
|
||||||
attributes: quick_xml::events::attributes::Attributes<'a>,
|
attributes: quick_xml::events::attributes::Attributes<'a>,
|
||||||
grid: &Arc<GridInfo>,
|
grid: &Arc<GridInfo>,
|
||||||
) -> Result<ButtonInfo> {
|
) -> Result<ButtonInfo> {
|
||||||
|
|
|
@ -6,11 +6,11 @@ use assetpath::AssetPath;
|
||||||
use serde_json::from_str;
|
use serde_json::from_str;
|
||||||
use utilities::prelude::*;
|
use utilities::prelude::*;
|
||||||
|
|
||||||
use quick_xml::{events::Event, Reader};
|
use quick_xml::{Reader, events::Event};
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::str::from_utf8;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::str::from_utf8;
|
||||||
use std::{convert::TryFrom, io::BufRead, sync::Arc};
|
use std::{convert::TryFrom, io::BufRead, sync::Arc};
|
||||||
|
|
||||||
use super::buttoninfo::ButtonInfo;
|
use super::buttoninfo::ButtonInfo;
|
||||||
|
@ -63,7 +63,7 @@ enum CurrentElement {
|
||||||
|
|
||||||
impl Validator {
|
impl Validator {
|
||||||
pub fn from_str(
|
pub fn from_str(
|
||||||
#[cfg(feature = "audio")] gui_handler: &Arc<GuiHandler>,
|
#[cfg(feature = "audio")] gui_handler: &GuiHandler,
|
||||||
s: &str,
|
s: &str,
|
||||||
) -> Result<Validator> {
|
) -> Result<Validator> {
|
||||||
Self::_new(
|
Self::_new(
|
||||||
|
@ -74,7 +74,7 @@ impl Validator {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
#[cfg(feature = "audio")] gui_handler: &Arc<GuiHandler>,
|
#[cfg(feature = "audio")] gui_handler: &GuiHandler,
|
||||||
path: &AssetPath,
|
path: &AssetPath,
|
||||||
) -> Result<Validator> {
|
) -> Result<Validator> {
|
||||||
Self::_new(
|
Self::_new(
|
||||||
|
@ -86,7 +86,7 @@ impl Validator {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn _new<T: BufRead>(
|
fn _new<T: BufRead>(
|
||||||
#[cfg(feature = "audio")] gui_handler: &Arc<GuiHandler>,
|
#[cfg(feature = "audio")] gui_handler: &GuiHandler,
|
||||||
mut reader: Reader<T>,
|
mut reader: Reader<T>,
|
||||||
) -> Result<Validator> {
|
) -> Result<Validator> {
|
||||||
// removes white spaces in texts
|
// removes white spaces in texts
|
||||||
|
@ -312,13 +312,13 @@ impl Validator {
|
||||||
}
|
}
|
||||||
Ok(Event::Text(ref e)) => match current_element {
|
Ok(Event::Text(ref e)) => match current_element {
|
||||||
CurrentElement::Root => {
|
CurrentElement::Root => {
|
||||||
return Err(anyhow::Error::msg("Text inside root not allowed"))
|
return Err(anyhow::Error::msg("Text inside root not allowed"));
|
||||||
}
|
}
|
||||||
CurrentElement::None => {
|
CurrentElement::None => {
|
||||||
return Err(anyhow::Error::msg("Text outside root not allowed"))
|
return Err(anyhow::Error::msg("Text outside root not allowed"));
|
||||||
}
|
}
|
||||||
CurrentElement::Grid(_) => {
|
CurrentElement::Grid(_) => {
|
||||||
return Err(anyhow::Error::msg("Text inside grid not allowed"))
|
return Err(anyhow::Error::msg("Text inside grid not allowed"));
|
||||||
}
|
}
|
||||||
CurrentElement::Icon(ref icon) => {
|
CurrentElement::Icon(ref icon) => {
|
||||||
*icon.text.write().unwrap() = e.unescape()?.to_string();
|
*icon.text.write().unwrap() = e.unescape()?.to_string();
|
||||||
|
@ -365,7 +365,7 @@ impl Validator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_start<'a>(
|
fn process_start<'a>(
|
||||||
#[cfg(feature = "audio")] gui_handler: &Arc<GuiHandler>,
|
#[cfg(feature = "audio")] gui_handler: &GuiHandler,
|
||||||
element: &quick_xml::events::BytesStart<'a>,
|
element: &quick_xml::events::BytesStart<'a>,
|
||||||
handle: &CurrentElement,
|
handle: &CurrentElement,
|
||||||
) -> Result<StartResult> {
|
) -> Result<StartResult> {
|
||||||
|
@ -479,7 +479,7 @@ impl Validator {
|
||||||
return Err(anyhow::Error::msg(format!(
|
return Err(anyhow::Error::msg(format!(
|
||||||
"Unexpected tag: {}",
|
"Unexpected tag: {}",
|
||||||
from_utf8(element.name().into_inner())?
|
from_utf8(element.name().into_inner())?
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,13 +140,13 @@ impl ButtonBuilder {
|
||||||
#[cfg(feature = "audio")]
|
#[cfg(feature = "audio")]
|
||||||
let click_sound = self
|
let click_sound = self
|
||||||
.click_sound
|
.click_sound
|
||||||
.map(|path| Audible::new(gui_handler.clone(), path))
|
.map(|path| Audible::new(gui_handler, path))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
#[cfg(feature = "audio")]
|
#[cfg(feature = "audio")]
|
||||||
let hover_sound = self
|
let hover_sound = self
|
||||||
.hover_sound
|
.hover_sound
|
||||||
.map(|path| Audible::new(gui_handler.clone(), path))
|
.map(|path| Audible::new(gui_handler, path))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
let clickable = Clickable::new(framable.clone(), click_executable.clone());
|
let clickable = Clickable::new(framable.clone(), click_executable.clone());
|
||||||
|
@ -314,9 +314,10 @@ impl Button {
|
||||||
|
|
||||||
pub fn set_callback<F>(&self, callback: F)
|
pub fn set_callback<F>(&self, callback: F)
|
||||||
where
|
where
|
||||||
F: Fn() -> Result<()> + Send + Sync + 'static,
|
F: Fn(&mut GuiHandler) -> Result<()> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.click_executable.set_callback(move |_, _| callback());
|
self.click_executable
|
||||||
|
.set_callback(move |gui_handler: &mut GuiHandler, _: ()| callback(gui_handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_select_callback<F>(&self, callback: F)
|
pub fn set_select_callback<F>(&self, callback: F)
|
||||||
|
@ -324,7 +325,7 @@ impl Button {
|
||||||
F: Fn(bool) -> Result<()> + Send + Sync + 'static,
|
F: Fn(bool) -> Result<()> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.on_select_executable
|
self.on_select_executable
|
||||||
.set_callback(|_m, select| callback(select));
|
.set_callback(move |_: &mut GuiHandler, select: bool| callback(select));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_custom_callback<F>(&self, callback: F)
|
pub fn set_custom_callback<F>(&self, callback: F)
|
||||||
|
@ -555,7 +556,7 @@ impl Button {
|
||||||
fn create_clicked_changed_callback(button: Arc<Button>) {
|
fn create_clicked_changed_callback(button: Arc<Button>) {
|
||||||
let button_weak = Arc::downgrade(&button);
|
let button_weak = Arc::downgrade(&button);
|
||||||
|
|
||||||
let clicked_changed = Box::new(move |gui_handler| {
|
let clicked_changed = Box::new(move |gui_handler: &mut GuiHandler| {
|
||||||
if let Some(button) = button_weak.upgrade() {
|
if let Some(button) = button_weak.upgrade() {
|
||||||
if button.clickable.clicked() {
|
if button.clickable.clicked() {
|
||||||
button.hoverable.set_hovered(gui_handler, false)?;
|
button.hoverable.set_hovered(gui_handler, false)?;
|
||||||
|
@ -577,7 +578,7 @@ impl Button {
|
||||||
fn create_selected_changed_callback(button: Arc<Button>) {
|
fn create_selected_changed_callback(button: Arc<Button>) {
|
||||||
let button_weak = Arc::downgrade(&button);
|
let button_weak = Arc::downgrade(&button);
|
||||||
|
|
||||||
let selected_changed = move |(gui_handler, selected)| {
|
let selected_changed = move |gui_handler: &mut GuiHandler, selected: bool| {
|
||||||
if let Some(button) = button_weak.upgrade() {
|
if let Some(button) = button_weak.upgrade() {
|
||||||
if selected {
|
if selected {
|
||||||
button.set_button_state(gui_handler, ButtonState::Selected)?;
|
button.set_button_state(gui_handler, ButtonState::Selected)?;
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::any::Any;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use super::ControllerButton;
|
use super::ControllerButton;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
macro_rules! callbacks {
|
macro_rules! callbacks {
|
||||||
($name:ident, $($cb:tt)*) => {
|
($name:ident, $($cb:tt)*) => {
|
||||||
|
@ -26,7 +27,7 @@ macro_rules! callbacks {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks!(ClickCallbacks, Fn() -> Result<()> + Send + Sync);
|
callbacks!(ClickCallbacks, Fn(&mut GuiHandler) -> Result<()> + Send + Sync);
|
||||||
callbacks!(SelectCallbacks, Fn(bool) -> anyhow::Result<()> + Send + Sync);
|
callbacks!(SelectCallbacks, Fn(bool) -> anyhow::Result<()> + Send + Sync);
|
||||||
callbacks!(CustomCallbacks, Fn(ControllerButton) -> anyhow::Result<bool> + Send + Sync);
|
callbacks!(CustomCallbacks, Fn(ControllerButton) -> anyhow::Result<bool> + Send + Sync);
|
||||||
callbacks!(VecCallbacks, Fn(&dyn Any) -> Result<()> + Send + Sync);
|
callbacks!(VecCallbacks, Fn(&dyn Any) -> Result<()> + Send + Sync);
|
||||||
|
@ -36,8 +37,8 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
fn normal_fn() -> impl Fn() -> Result<()> + Send + Sync {
|
fn normal_fn() -> impl Fn(&mut GuiHandler) -> Result<()> + Send + Sync {
|
||||||
|| Ok(())
|
|_| Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -47,7 +48,10 @@ mod test {
|
||||||
impl Test {
|
impl Test {
|
||||||
fn set_click_callbacks(
|
fn set_click_callbacks(
|
||||||
&self,
|
&self,
|
||||||
_callbacks: Vec<(&str, Box<dyn Fn() -> Result<()> + Send + Sync>)>,
|
_callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -337,10 +337,10 @@ impl Grid {
|
||||||
self.framable.allow_size_scale(gui_handler, false)
|
self.framable.allow_size_scale(gui_handler, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(
|
pub fn connect<'a>(
|
||||||
&self,
|
&self,
|
||||||
direction: ConnectDirection,
|
direction: ConnectDirection,
|
||||||
elements: impl IntoIterator<Item = (usize, &Arc<Selectable>)>,
|
elements: impl IntoIterator<Item = (usize, &'a Arc<Selectable>)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (index, selectable) in elements {
|
for (index, selectable) in elements {
|
||||||
match direction {
|
match direction {
|
||||||
|
@ -499,8 +499,8 @@ impl Grid {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_from(
|
pub fn try_from(
|
||||||
grid_info: &GridInfo,
|
|
||||||
gui_handler: &mut GuiHandler,
|
gui_handler: &mut GuiHandler,
|
||||||
|
grid_info: &GridInfo,
|
||||||
top_level: bool,
|
top_level: bool,
|
||||||
) -> Result<Arc<Self>> {
|
) -> Result<Arc<Self>> {
|
||||||
let grid = Grid::new(
|
let grid = Grid::new(
|
||||||
|
|
|
@ -9,8 +9,8 @@ pub trait TopLevelGui: Send + Sync {
|
||||||
fn top_gui(&self) -> Option<&dyn TopGui>;
|
fn top_gui(&self) -> Option<&dyn TopGui>;
|
||||||
fn elements(&self) -> Option<&HashMap<String, UiElement>>;
|
fn elements(&self) -> Option<&HashMap<String, UiElement>>;
|
||||||
fn functionality(&self) -> Option<&dyn Functionality>;
|
fn functionality(&self) -> Option<&dyn Functionality>;
|
||||||
fn enable(&self) -> Result<()>;
|
fn enable(&self, gui_handler: &mut GuiHandler) -> Result<()>;
|
||||||
fn disable(&self) -> Result<()>;
|
fn disable(&self, gui_handler: &mut GuiHandler) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn any_to<T>(any: &dyn Any) -> Result<&T>
|
pub fn any_to<T>(any: &dyn Any) -> Result<&T>
|
||||||
|
@ -26,7 +26,10 @@ where
|
||||||
pub trait Functionality {
|
pub trait Functionality {
|
||||||
fn set_click_callbacks(
|
fn set_click_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(&str, Box<dyn Fn() -> Result<()> + Send + Sync>)>,
|
callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
|
|
||||||
fn set_select_callbacks(
|
fn set_select_callbacks(
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub struct Audible {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Audible {
|
impl Audible {
|
||||||
pub fn new(gui_handler: Arc<GuiHandler>, mut path: AssetPath) -> Result<Arc<Self>> {
|
pub fn new(gui_handler: &GuiHandler, mut path: AssetPath) -> Result<Arc<Self>> {
|
||||||
if !path.has_prefix() {
|
if !path.has_prefix() {
|
||||||
path.set_prefix(
|
path.set_prefix(
|
||||||
&gui_handler
|
&gui_handler
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
/// A trait that is used by the gui handler as the target for input
|
/// A trait that is used by the gui handler as the target for input
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub trait TopGui: Send + Sync {
|
pub trait TopGui: Send + Sync {
|
||||||
/// Decline method which is executed on `InputMap::B` press
|
/// Decline method which is executed on `InputMap::B` press
|
||||||
fn decline(&self) -> Result<()>;
|
fn decline(&self, gui_handler: &mut GuiHandler) -> Result<()>;
|
||||||
|
|
||||||
/// Method which is executed on `InputMap::RightButton` press
|
/// Method which is executed on `InputMap::RightButton` press
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `second_level` adds support for multiple tab layers, e.g. RB and RT press on controller
|
/// * `second_level` adds support for multiple tab layers, e.g. RB and RT press on controller
|
||||||
fn next_tab(&self, second_level: bool) -> Result<()>;
|
fn next_tab(&self, gui_handler: &mut GuiHandler, second_level: bool) -> Result<()>;
|
||||||
|
|
||||||
/// Method which is executed on `InputMap::LeftButton` press
|
/// Method which is executed on `InputMap::LeftButton` press
|
||||||
/// ///
|
/// ///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `second_level` adds support for multiple tab layers, e.g. RB and RT press on controller
|
/// * `second_level` adds support for multiple tab layers, e.g. RB and RT press on controller
|
||||||
fn previous_tab(&self, second_level: bool) -> Result<()>;
|
fn previous_tab(&self, gui_handler: &mut GuiHandler, second_level: bool) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -736,36 +736,36 @@ impl GuiHandler {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decline_topgui(&self) -> Result<bool> {
|
pub fn decline_topgui(&mut self) -> Result<bool> {
|
||||||
// workaround for unwanted borrowing behaviour inside decline function
|
// workaround for unwanted borrowing behaviour inside decline function
|
||||||
let opt_topgui = self.top_ui.as_ref().cloned();
|
let opt_topgui = self.top_ui.as_ref().cloned();
|
||||||
|
|
||||||
if let Some(topgui) = opt_topgui {
|
if let Some(topgui) = opt_topgui {
|
||||||
topgui.decline()?;
|
topgui.decline(self)?;
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_tab_topgui(&self, second_level: bool) -> Result<bool> {
|
pub fn next_tab_topgui(&mut self, second_level: bool) -> Result<bool> {
|
||||||
// workaround for unwanted borrowing behaviour inside decline function
|
// workaround for unwanted borrowing behaviour inside decline function
|
||||||
let opt_topgui = self.top_ui.as_ref().cloned();
|
let opt_topgui = self.top_ui.as_ref().cloned();
|
||||||
|
|
||||||
if let Some(topgui) = opt_topgui {
|
if let Some(topgui) = opt_topgui {
|
||||||
topgui.next_tab(second_level)?;
|
topgui.next_tab(self, second_level)?;
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn previous_tab_topgui(&self, second_level: bool) -> Result<bool> {
|
pub fn previous_tab_topgui(&mut self, second_level: bool) -> Result<bool> {
|
||||||
// workaround for unwanted borrowing behaviour inside decline function
|
// workaround for unwanted borrowing behaviour inside decline function
|
||||||
let opt_topgui = self.top_ui.as_ref().cloned();
|
let opt_topgui = self.top_ui.as_ref().cloned();
|
||||||
|
|
||||||
if let Some(topgui) = opt_topgui {
|
if let Some(topgui) = opt_topgui {
|
||||||
topgui.previous_tab(second_level)?;
|
topgui.previous_tab(self, second_level)?;
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -852,12 +852,12 @@ impl GuiHandler {
|
||||||
self.needs_update = true;
|
self.needs_update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_top_gui(&mut self, top_gui: impl Into<Option<Arc<dyn TopGui>>>) {
|
pub fn set_top_gui(&mut self, top_gui: Option<Arc<dyn TopGui>>) {
|
||||||
self.top_ui = top_gui.into();
|
self.top_ui = top_gui;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_tooltip(&mut self, tooltip: impl Into<Option<Arc<dyn TopGui>>>) {
|
pub fn set_tooltip(&mut self, tooltip: Option<Arc<dyn TopGui>>) {
|
||||||
self.tooltip_ui = tooltip.into();
|
self.tooltip_ui = tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_callback<F: FnOnce(&mut Self) -> Result<()> + Send + Sync + 'static>(
|
pub(crate) fn add_callback<F: FnOnce(&mut Self) -> Result<()> + Send + Sync + 'static>(
|
||||||
|
|
|
@ -25,21 +25,22 @@ pub struct Keyboard {
|
||||||
|
|
||||||
mode: Arc<RwLock<KeyboardMode>>,
|
mode: Arc<RwLock<KeyboardMode>>,
|
||||||
|
|
||||||
decline_callback: Arc<RwLock<Option<Box<dyn Fn() -> Result<()> + Send + Sync>>>>,
|
decline_callback: Arc<RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>>,
|
||||||
accept_callback: Arc<RwLock<Option<Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>>>>,
|
accept_callback: Arc<RwLock<Option<Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>>>>,
|
||||||
|
|
||||||
elements: HashMap<String, UiElement>,
|
elements: HashMap<String, UiElement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Keyboard {
|
impl Keyboard {
|
||||||
pub fn new(gui_handler: &GuiHandler) -> Result<Arc<Self>> {
|
pub fn new(gui_handler: &mut GuiHandler) -> Result<Arc<Self>> {
|
||||||
let text_field_gui: Arc<GuiBuilder> =
|
let text_field_gui: Arc<GuiBuilder> =
|
||||||
GuiBuilder::from_str(gui_handler, include_str!("text_field.xml"))?;
|
GuiBuilder::from_str(gui_handler, include_str!("text_field.xml"))?;
|
||||||
|
|
||||||
let text_field: Arc<TextField> = text_field_gui.element("field")?;
|
let text_field: Arc<TextField> = text_field_gui.element("field")?;
|
||||||
|
|
||||||
let decline_callback: Arc<RwLock<Option<Box<dyn Fn() -> Result<()> + Send + Sync>>>> =
|
let decline_callback: Arc<
|
||||||
Arc::new(RwLock::new(None));
|
RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
||||||
|
> = Arc::new(RwLock::new(None));
|
||||||
|
|
||||||
let accept_callback: Arc<
|
let accept_callback: Arc<
|
||||||
RwLock<Option<Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>>>,
|
RwLock<Option<Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>>>,
|
||||||
|
@ -80,10 +81,12 @@ impl Keyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(
|
fn setup(
|
||||||
gui_handler: &Arc<GuiHandler>,
|
gui_handler: &mut GuiHandler,
|
||||||
textfield: Arc<TextField>,
|
textfield: Arc<TextField>,
|
||||||
mode: &Arc<RwLock<KeyboardMode>>,
|
mode: &Arc<RwLock<KeyboardMode>>,
|
||||||
decline_callback: Arc<RwLock<Option<Box<dyn Fn() -> Result<()> + Send + Sync>>>>,
|
decline_callback: Arc<
|
||||||
|
RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
||||||
|
>,
|
||||||
accept_callback: Arc<RwLock<Option<Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>>>>,
|
accept_callback: Arc<RwLock<Option<Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>>>>,
|
||||||
) -> Result<(Arc<GuiBuilder>, Arc<GuiBuilder>, Arc<GuiBuilder>)> {
|
) -> Result<(Arc<GuiBuilder>, Arc<GuiBuilder>, Arc<GuiBuilder>)> {
|
||||||
let lower_case = GuiBuilder::from_str(gui_handler, include_str!("lower_case.xml"))?;
|
let lower_case = GuiBuilder::from_str(gui_handler, include_str!("lower_case.xml"))?;
|
||||||
|
@ -190,9 +193,9 @@ impl Keyboard {
|
||||||
Self::set_text_callback(&specials, ".", textfield.clone())?;
|
Self::set_text_callback(&specials, ".", textfield.clone())?;
|
||||||
Self::set_text_callback(&specials, "_", textfield.clone())?;
|
Self::set_text_callback(&specials, "_", textfield.clone())?;
|
||||||
|
|
||||||
let back = Box::new(move || {
|
let back = Box::new(move |gui_handler: &mut GuiHandler| {
|
||||||
if let Some(callback) = decline_callback.read().unwrap().as_ref() {
|
if let Some(callback) = decline_callback.read().unwrap().as_ref() {
|
||||||
(callback)()?;
|
(callback)(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -202,7 +205,7 @@ impl Keyboard {
|
||||||
let weak_textfield = Arc::downgrade(&textfield);
|
let weak_textfield = Arc::downgrade(&textfield);
|
||||||
let weak_accept = Arc::downgrade(&accept_callback);
|
let weak_accept = Arc::downgrade(&accept_callback);
|
||||||
|
|
||||||
Box::new(move || {
|
Box::new(move |_: &mut GuiHandler| {
|
||||||
if let Some(textfield) = weak_textfield.upgrade() {
|
if let Some(textfield) = weak_textfield.upgrade() {
|
||||||
if let Some(accept_callback) = weak_accept.upgrade() {
|
if let Some(accept_callback) = weak_accept.upgrade() {
|
||||||
if let Some(text) = textfield.text() {
|
if let Some(text) = textfield.text() {
|
||||||
|
@ -222,15 +225,15 @@ impl Keyboard {
|
||||||
let weak_lower = Arc::downgrade(&lower_case);
|
let weak_lower = Arc::downgrade(&lower_case);
|
||||||
let weak_upper = Arc::downgrade(&upper_case);
|
let weak_upper = Arc::downgrade(&upper_case);
|
||||||
|
|
||||||
Box::new(move || {
|
Box::new(move |gui_handler: &mut GuiHandler| {
|
||||||
if let Some(lower) = weak_lower.upgrade() {
|
if let Some(lower) = weak_lower.upgrade() {
|
||||||
if let Some(upper) = weak_upper.upgrade() {
|
if let Some(upper) = weak_upper.upgrade() {
|
||||||
let mut mode = mode.write().unwrap();
|
let mut mode = mode.write().unwrap();
|
||||||
|
|
||||||
if let KeyboardMode::LowerCase = mode.deref() {
|
if let KeyboardMode::LowerCase = mode.deref() {
|
||||||
*mode = KeyboardMode::UpperCase;
|
*mode = KeyboardMode::UpperCase;
|
||||||
lower.disable()?;
|
lower.disable(gui_handler)?;
|
||||||
upper.enable()?;
|
upper.enable(gui_handler)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,15 +247,15 @@ impl Keyboard {
|
||||||
let weak_upper = Arc::downgrade(&upper_case);
|
let weak_upper = Arc::downgrade(&upper_case);
|
||||||
let weak_specials = Arc::downgrade(&specials);
|
let weak_specials = Arc::downgrade(&specials);
|
||||||
|
|
||||||
Box::new(move || {
|
Box::new(move |gui_handler: &mut GuiHandler| {
|
||||||
if let Some(specials) = weak_specials.upgrade() {
|
if let Some(specials) = weak_specials.upgrade() {
|
||||||
if let Some(upper) = weak_upper.upgrade() {
|
if let Some(upper) = weak_upper.upgrade() {
|
||||||
let mut mode = mode.write().unwrap();
|
let mut mode = mode.write().unwrap();
|
||||||
|
|
||||||
if let KeyboardMode::UpperCase = mode.deref() {
|
if let KeyboardMode::UpperCase = mode.deref() {
|
||||||
*mode = KeyboardMode::Specials;
|
*mode = KeyboardMode::Specials;
|
||||||
upper.disable()?;
|
upper.disable(gui_handler)?;
|
||||||
specials.enable()?;
|
specials.enable(gui_handler)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,15 +269,15 @@ impl Keyboard {
|
||||||
let weak_lower = Arc::downgrade(&lower_case);
|
let weak_lower = Arc::downgrade(&lower_case);
|
||||||
let weak_specials = Arc::downgrade(&specials);
|
let weak_specials = Arc::downgrade(&specials);
|
||||||
|
|
||||||
Box::new(move || {
|
Box::new(move |gui_handler: &mut GuiHandler| {
|
||||||
if let Some(lower) = weak_lower.upgrade() {
|
if let Some(lower) = weak_lower.upgrade() {
|
||||||
if let Some(specials) = weak_specials.upgrade() {
|
if let Some(specials) = weak_specials.upgrade() {
|
||||||
let mut mode = mode.write().unwrap();
|
let mut mode = mode.write().unwrap();
|
||||||
|
|
||||||
if let KeyboardMode::Specials = mode.deref() {
|
if let KeyboardMode::Specials = mode.deref() {
|
||||||
*mode = KeyboardMode::LowerCase;
|
*mode = KeyboardMode::LowerCase;
|
||||||
specials.disable()?;
|
specials.disable(gui_handler)?;
|
||||||
lower.enable()?;
|
lower.enable(gui_handler)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,9 +289,9 @@ impl Keyboard {
|
||||||
let space_bar = {
|
let space_bar = {
|
||||||
let weak_textfield = Arc::downgrade(&textfield);
|
let weak_textfield = Arc::downgrade(&textfield);
|
||||||
|
|
||||||
Box::new(move || {
|
Box::new(move |gui_handler: &mut GuiHandler| {
|
||||||
if let Some(text_field) = weak_textfield.upgrade() {
|
if let Some(text_field) = weak_textfield.upgrade() {
|
||||||
text_field.add_letter(' ')?;
|
text_field.add_letter(gui_handler, ' ')?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -327,11 +330,11 @@ impl Keyboard {
|
||||||
let weak_textfield = Arc::downgrade(&textfield);
|
let weak_textfield = Arc::downgrade(&textfield);
|
||||||
let weak_button = Arc::downgrade(&button_ref);
|
let weak_button = Arc::downgrade(&button_ref);
|
||||||
|
|
||||||
button_ref.set_callback(Box::new(move || {
|
button_ref.set_callback(Box::new(move |gui_handler: &mut GuiHandler| {
|
||||||
if let Some(textfield) = weak_textfield.upgrade() {
|
if let Some(textfield) = weak_textfield.upgrade() {
|
||||||
if let Some(button) = weak_button.upgrade() {
|
if let Some(button) = weak_button.upgrade() {
|
||||||
if let Some(text) = button.text()? {
|
if let Some(text) = button.text()? {
|
||||||
textfield.add_letter(text.as_bytes()[0] as char)?;
|
textfield.add_letter(gui_handler, text.as_bytes()[0] as char)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,22 +347,22 @@ impl Keyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopGui for Keyboard {
|
impl TopGui for Keyboard {
|
||||||
fn decline(&self) -> Result<()> {
|
fn decline(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
if let Some(callback) = self.decline_callback.read().unwrap().as_ref() {
|
if let Some(callback) = self.decline_callback.read().unwrap().as_ref() {
|
||||||
(callback)()?;
|
(callback)(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_tab(&self, _: bool) -> Result<()> {
|
fn next_tab(&self, _gui_handler: &mut GuiHandler, _: bool) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn previous_tab(&self, second_level: bool) -> Result<()> {
|
fn previous_tab(&self, gui_handler: &mut GuiHandler, second_level: bool) -> Result<()> {
|
||||||
// abuse event
|
// abuse event
|
||||||
if !second_level {
|
if !second_level {
|
||||||
self.text_field.remove_last()?;
|
self.text_field.remove_last(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -377,7 +380,7 @@ impl Visibility for Keyboard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_visibility(&self, visibility: bool) -> Result<()> {
|
fn set_visibility(&self, gui_handler: &mut GuiHandler, visibility: bool) -> Result<()> {
|
||||||
let mode = self.mode.read().unwrap();
|
let mode = self.mode.read().unwrap();
|
||||||
|
|
||||||
let gui = match mode.deref() {
|
let gui = match mode.deref() {
|
||||||
|
@ -387,11 +390,11 @@ impl Visibility for Keyboard {
|
||||||
};
|
};
|
||||||
|
|
||||||
if visibility {
|
if visibility {
|
||||||
gui.enable()?;
|
gui.enable(gui_handler)?;
|
||||||
self.text_field_gui.enable()?;
|
self.text_field_gui.enable(gui_handler)?;
|
||||||
} else {
|
} else {
|
||||||
gui.disable()?;
|
gui.disable(gui_handler)?;
|
||||||
self.text_field_gui.disable()?;
|
self.text_field_gui.disable(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -429,15 +432,15 @@ impl TopLevelGui for Keyboard {
|
||||||
Some(self)
|
Some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(&self) -> Result<()> {
|
fn enable(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
self.set_visibility(true)?;
|
self.set_visibility(gui_handler, true)?;
|
||||||
self.text_field.focus_input()?;
|
self.text_field.focus_input(gui_handler)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable(&self) -> Result<()> {
|
fn disable(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
self.set_visibility(false)?;
|
self.set_visibility(gui_handler, false)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -446,7 +449,10 @@ impl TopLevelGui for Keyboard {
|
||||||
impl Functionality for Keyboard {
|
impl Functionality for Keyboard {
|
||||||
fn set_click_callbacks(
|
fn set_click_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(&str, Box<dyn Fn() -> Result<()> + Send + Sync>)>,
|
callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (name, callback) in callbacks {
|
for (name, callback) in callbacks {
|
||||||
if name == "decline" {
|
if name == "decline" {
|
||||||
|
|
139
src/states.rs
139
src/states.rs
|
@ -7,19 +7,21 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex, RwLock, Weak};
|
use std::sync::{Arc, Mutex, RwLock, Weak};
|
||||||
|
|
||||||
pub trait FutureStateChange: Fn() -> Result<()> + Send + Sync {
|
pub trait FutureStateChange: Fn(&mut GuiHandler) -> Result<()> + Send + Sync {
|
||||||
fn clone_box<'a>(&self) -> Box<dyn 'a + FutureStateChange>
|
fn clone_box<'a>(&self) -> Box<dyn 'a + FutureStateChange>
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
|
||||||
fn as_fn(&self) -> &(dyn Fn() -> Result<()> + Send + Sync)
|
fn as_fn(&self) -> &(dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync)
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_static(&'static self) -> &'static (dyn Fn() -> Result<()> + Send + Sync + 'static)
|
fn as_static(
|
||||||
|
&'static self,
|
||||||
|
) -> &'static (dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync + 'static)
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
@ -27,7 +29,7 @@ pub trait FutureStateChange: Fn() -> Result<()> + Send + Sync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Fn() -> Result<()> + Clone + Send + Sync> FutureStateChange for F {
|
impl<F: Fn(&mut GuiHandler) -> Result<()> + Clone + Send + Sync> FutureStateChange for F {
|
||||||
fn clone_box<'a>(&self) -> Box<dyn 'a + FutureStateChange>
|
fn clone_box<'a>(&self) -> Box<dyn 'a + FutureStateChange>
|
||||||
where
|
where
|
||||||
Self: 'a,
|
Self: 'a,
|
||||||
|
@ -47,12 +49,12 @@ struct State {
|
||||||
|
|
||||||
top_level_gui: Arc<dyn TopLevelGui>,
|
top_level_gui: Arc<dyn TopLevelGui>,
|
||||||
|
|
||||||
on_activate: RwLock<Option<Box<dyn Fn() -> Result<()> + Send + Sync>>>,
|
on_activate: RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
||||||
on_deactivate: RwLock<Option<Box<dyn Fn() -> Result<()> + Send + Sync>>>,
|
on_deactivate: RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
||||||
|
|
||||||
next_tab: RwLock<Option<Box<dyn Fn() -> Result<()> + Send + Sync>>>,
|
next_tab: RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
||||||
previous_tab: RwLock<Option<Box<dyn Fn() -> Result<()> + Send + Sync>>>,
|
previous_tab: RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
||||||
decline: RwLock<Option<Box<dyn Fn() -> Result<()> + Send + Sync>>>,
|
decline: RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opaque handle for a State
|
/// Opaque handle for a State
|
||||||
|
@ -148,16 +150,21 @@ impl GetElement<ProgressBar> for StateHandle {
|
||||||
/// Update type
|
/// Update type
|
||||||
pub enum StateUpdateType<'a> {
|
pub enum StateUpdateType<'a> {
|
||||||
/// Updates the callback which is executed on next tab event
|
/// Updates the callback which is executed on next tab event
|
||||||
NextTab(Option<Box<dyn Fn() -> Result<()> + Send + Sync>>),
|
NextTab(Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>),
|
||||||
|
|
||||||
/// Updates the callback which is executed on previous tab event
|
/// Updates the callback which is executed on previous tab event
|
||||||
PreviousTab(Option<Box<dyn Fn() -> Result<()> + Send + Sync>>),
|
PreviousTab(Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>),
|
||||||
|
|
||||||
/// Updates the callback which is executed on decline event
|
/// Updates the callback which is executed on decline event
|
||||||
Decline(Option<Box<dyn Fn() -> Result<()> + Send + Sync>>),
|
Decline(Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>),
|
||||||
|
|
||||||
/// Updates callbacks by identifier
|
/// Updates callbacks by identifier
|
||||||
ClickCallbacks(Vec<(&'a str, Box<dyn Fn() -> Result<()> + Send + Sync>)>),
|
ClickCallbacks(
|
||||||
|
Vec<(
|
||||||
|
&'a str,
|
||||||
|
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
|
),
|
||||||
|
|
||||||
/// Updates callbacks by identifier
|
/// Updates callbacks by identifier
|
||||||
SelectCallbacks(Vec<(&'a str, Box<CustomCallback<bool, ()>>)>),
|
SelectCallbacks(Vec<(&'a str, Box<CustomCallback<bool, ()>>)>),
|
||||||
|
@ -169,10 +176,10 @@ pub enum StateUpdateType<'a> {
|
||||||
VecCallbacks(Vec<(&'a str, Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>)>),
|
VecCallbacks(Vec<(&'a str, Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>)>),
|
||||||
|
|
||||||
/// Updates the callback which is executed when this state gets activated on state change
|
/// Updates the callback which is executed when this state gets activated on state change
|
||||||
OnActivate(Option<Box<dyn Fn() -> Result<()> + Send + Sync>>),
|
OnActivate(Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>),
|
||||||
|
|
||||||
/// Updates the callback which is executed when this state gets deactivated on state change
|
/// Updates the callback which is executed when this state gets deactivated on state change
|
||||||
OnDeactivate(Option<Box<dyn Fn() -> Result<()> + Send + Sync>>),
|
OnDeactivate(Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type of the state to be created
|
/// Type of the state to be created
|
||||||
|
@ -204,8 +211,6 @@ impl<'a, T: TopLevelGui + 'static> From<T> for CreationType<'a> {
|
||||||
|
|
||||||
/// Collection and handler for your UI (basically a state machine)
|
/// Collection and handler for your UI (basically a state machine)
|
||||||
pub struct States {
|
pub struct States {
|
||||||
gui_handler: Arc<GuiHandler>,
|
|
||||||
|
|
||||||
states: HashMap<String, Arc<State>>,
|
states: HashMap<String, Arc<State>>,
|
||||||
current_state: Arc<Mutex<Option<Arc<State>>>>,
|
current_state: Arc<Mutex<Option<Arc<State>>>>,
|
||||||
|
|
||||||
|
@ -215,10 +220,8 @@ pub struct States {
|
||||||
|
|
||||||
impl States {
|
impl States {
|
||||||
/// Creates an empty States struct
|
/// Creates an empty States struct
|
||||||
pub fn new(gui_handler: Arc<GuiHandler>) -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
Ok(States {
|
Ok(States {
|
||||||
gui_handler,
|
|
||||||
|
|
||||||
states: HashMap::new(),
|
states: HashMap::new(),
|
||||||
current_state: Arc::new(Mutex::new(None)),
|
current_state: Arc::new(Mutex::new(None)),
|
||||||
|
|
||||||
|
@ -246,12 +249,13 @@ impl States {
|
||||||
/// Adds a single state
|
/// Adds a single state
|
||||||
pub fn add_state<'a>(
|
pub fn add_state<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
gui_handler: &mut GuiHandler,
|
||||||
id: &str,
|
id: &str,
|
||||||
creation_type: impl Into<CreationType<'a>>,
|
creation_type: impl Into<CreationType<'a>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.states.insert(
|
self.states.insert(
|
||||||
id.to_string(),
|
id.to_string(),
|
||||||
State::new(&self.gui_handler, id, creation_type.into())?,
|
State::new(gui_handler, id, creation_type.into())?,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -270,15 +274,15 @@ impl States {
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `id` - Set state with the given identifier or None
|
/// * `id` - Set state with the given identifier or None
|
||||||
pub fn set_state<'b>(&self, id: impl Into<Option<&'b str>>) -> Result<()> {
|
pub fn set_state<'b>(
|
||||||
|
&self,
|
||||||
|
gui_handler: &mut GuiHandler,
|
||||||
|
id: impl Into<Option<&'b str>>,
|
||||||
|
) -> Result<()> {
|
||||||
Self::_set_state(
|
Self::_set_state(
|
||||||
id.into().map(|id| self.get_state(id)).transpose()?,
|
id.into().map(|id| self.get_state(id)).transpose()?,
|
||||||
&mut *self.current_state.lock().unwrap(),
|
&mut *self.current_state.lock().unwrap(),
|
||||||
if self.control_top_gui {
|
gui_handler,
|
||||||
Some(self.gui_handler.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
self.log_state_change,
|
self.log_state_change,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -286,7 +290,7 @@ impl States {
|
||||||
fn _set_state(
|
fn _set_state(
|
||||||
state: Option<Arc<State>>,
|
state: Option<Arc<State>>,
|
||||||
current: &mut Option<Arc<State>>,
|
current: &mut Option<Arc<State>>,
|
||||||
gui_handler: Option<Arc<GuiHandler>>,
|
gui_handler: &mut GuiHandler,
|
||||||
logging: bool,
|
logging: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if let Some(old_state) = current {
|
if let Some(old_state) = current {
|
||||||
|
@ -298,17 +302,14 @@ impl States {
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute deactivate on old state
|
// execute deactivate on old state
|
||||||
old_state.deactivate()?;
|
old_state.deactivate(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set new state, either no state or requested state
|
// set new state, either no state or requested state
|
||||||
match state {
|
match state {
|
||||||
Some(state) => {
|
Some(state) => {
|
||||||
state.activate()?;
|
state.activate(gui_handler)?;
|
||||||
|
gui_handler.set_top_gui(Some(state.clone()));
|
||||||
if let Some(gui_handler) = gui_handler {
|
|
||||||
gui_handler.set_top_gui(Some(state.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if logging {
|
if logging {
|
||||||
println!("Change UI State to {}", state.name);
|
println!("Change UI State to {}", state.name);
|
||||||
|
@ -317,9 +318,7 @@ impl States {
|
||||||
*current = Some(state);
|
*current = Some(state);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let Some(gui_handler) = gui_handler {
|
gui_handler.set_top_gui(None);
|
||||||
gui_handler.set_top_gui(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
if logging {
|
if logging {
|
||||||
println!("Change UI State to None");
|
println!("Change UI State to None");
|
||||||
|
@ -353,19 +352,14 @@ impl States {
|
||||||
let state: Option<Arc<State>> = id.into().map(|id| self.get_state(id)).transpose()?;
|
let state: Option<Arc<State>> = id.into().map(|id| self.get_state(id)).transpose()?;
|
||||||
let weak_state = state.map(|s| Arc::downgrade(&s));
|
let weak_state = state.map(|s| Arc::downgrade(&s));
|
||||||
let weak_current_state = Arc::downgrade(&self.current_state);
|
let weak_current_state = Arc::downgrade(&self.current_state);
|
||||||
let gui_handler = if self.control_top_gui {
|
|
||||||
Some(Arc::downgrade(&self.gui_handler))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let logging = self.log_state_change;
|
let logging = self.log_state_change;
|
||||||
|
|
||||||
Ok(Box::new(move || {
|
Ok(Box::new(move |gui_handler: &mut GuiHandler| {
|
||||||
if let Some(current) = weak_current_state.upgrade() {
|
if let Some(current) = weak_current_state.upgrade() {
|
||||||
Self::_set_state(
|
Self::_set_state(
|
||||||
weak_state.as_ref().map(|w| w.upgrade()).flatten(),
|
weak_state.as_ref().map(|w| w.upgrade()).flatten(),
|
||||||
&mut *current.lock().unwrap(),
|
&mut *current.lock().unwrap(),
|
||||||
gui_handler.as_ref().map(|h| h.upgrade()).flatten(),
|
gui_handler,
|
||||||
logging,
|
logging,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
@ -377,7 +371,7 @@ impl States {
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
fn new<'a>(
|
fn new<'a>(
|
||||||
gui_handler: &Arc<GuiHandler>,
|
gui_handler: &mut GuiHandler,
|
||||||
name: &str,
|
name: &str,
|
||||||
creation_type: CreationType<'a>,
|
creation_type: CreationType<'a>,
|
||||||
) -> Result<Arc<Self>> {
|
) -> Result<Arc<Self>> {
|
||||||
|
@ -435,56 +429,71 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate(&self) -> Result<()> {
|
fn activate(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
self.top_level_gui.enable()?;
|
self.top_level_gui.enable(gui_handler)?;
|
||||||
|
|
||||||
if let Some(activate) = self.on_activate.read().unwrap().as_ref() {
|
if let Some(activate) = self.on_activate.read().unwrap().as_ref() {
|
||||||
(activate)()?;
|
(activate)(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deactivate(&self) -> Result<()> {
|
fn deactivate(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
self.top_level_gui.disable()?;
|
self.top_level_gui.disable(gui_handler)?;
|
||||||
|
|
||||||
if let Some(deactivate) = self.on_deactivate.read().unwrap().as_ref() {
|
if let Some(deactivate) = self.on_deactivate.read().unwrap().as_ref() {
|
||||||
(deactivate)()?;
|
(deactivate)(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_on_activate(&self, on_activate: Option<Box<dyn Fn() -> Result<()> + Send + Sync>>) {
|
fn set_on_activate(
|
||||||
|
&self,
|
||||||
|
on_activate: Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>,
|
||||||
|
) {
|
||||||
*self.on_activate.write().unwrap() = on_activate;
|
*self.on_activate.write().unwrap() = on_activate;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_on_deactivate(&self, on_deactivate: Option<Box<dyn Fn() -> Result<()> + Send + Sync>>) {
|
fn set_on_deactivate(
|
||||||
|
&self,
|
||||||
|
on_deactivate: Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>,
|
||||||
|
) {
|
||||||
*self.on_deactivate.write().unwrap() = on_deactivate;
|
*self.on_deactivate.write().unwrap() = on_deactivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_previous_tab(&self, previous_tab: Option<Box<dyn Fn() -> Result<()> + Send + Sync>>) {
|
fn set_previous_tab(
|
||||||
|
&self,
|
||||||
|
previous_tab: Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>,
|
||||||
|
) {
|
||||||
*self.previous_tab.write().unwrap() = previous_tab;
|
*self.previous_tab.write().unwrap() = previous_tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_next_tab(&self, next_tab: Option<Box<dyn Fn() -> Result<()> + Send + Sync>>) {
|
fn set_next_tab(
|
||||||
|
&self,
|
||||||
|
next_tab: Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>,
|
||||||
|
) {
|
||||||
*self.next_tab.write().unwrap() = next_tab;
|
*self.next_tab.write().unwrap() = next_tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_decline(&self, decline: Option<Box<dyn Fn() -> Result<()> + Send + Sync>>) {
|
fn set_decline(
|
||||||
|
&self,
|
||||||
|
decline: Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>,
|
||||||
|
) {
|
||||||
*self.decline.write().unwrap() = decline;
|
*self.decline.write().unwrap() = decline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopGui for State {
|
impl TopGui for State {
|
||||||
fn decline(&self) -> Result<()> {
|
fn decline(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
match self.decline.read().unwrap().as_ref() {
|
match self.decline.read().unwrap().as_ref() {
|
||||||
Some(decline) => {
|
Some(decline) => {
|
||||||
(decline)()?;
|
(decline)(gui_handler)?;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||||
top_gui.decline()?;
|
top_gui.decline(gui_handler)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,14 +501,14 @@ impl TopGui for State {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_tab(&self, second_level: bool) -> Result<()> {
|
fn next_tab(&self, gui_handler: &mut GuiHandler, second_level: bool) -> Result<()> {
|
||||||
match self.next_tab.read().unwrap().as_ref() {
|
match self.next_tab.read().unwrap().as_ref() {
|
||||||
Some(next_tab) => {
|
Some(next_tab) => {
|
||||||
(next_tab)()?;
|
(next_tab)(gui_handler)?;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||||
top_gui.next_tab(second_level)?;
|
top_gui.next_tab(gui_handler, second_level)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,14 +516,14 @@ impl TopGui for State {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn previous_tab(&self, second_level: bool) -> Result<()> {
|
fn previous_tab(&self, gui_handler: &mut GuiHandler, second_level: bool) -> Result<()> {
|
||||||
match self.previous_tab.read().unwrap().as_ref() {
|
match self.previous_tab.read().unwrap().as_ref() {
|
||||||
Some(previous_tab) => {
|
Some(previous_tab) => {
|
||||||
(previous_tab)()?;
|
(previous_tab)(gui_handler)?;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||||
top_gui.previous_tab(second_level)?;
|
top_gui.previous_tab(gui_handler, second_level)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue