Compare commits
3 commits
2f1b4688af
...
9265d66418
Author | SHA1 | Date | |
---|---|---|---|
9265d66418 | |||
68b564fa18 | |||
1383cd5c4d |
6 changed files with 376 additions and 285 deletions
|
@ -5,7 +5,7 @@ authors = ["hodasemi <michaelh.95@t-online.de>"]
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
quick-xml = "0.31.0"
|
||||
quick-xml = "0.37.0"
|
||||
serde = { version = "1.0.203", features = ["derive"] }
|
||||
serde_json = { version = "1.0.120" }
|
||||
paste = "1.0.15"
|
||||
|
|
|
@ -190,8 +190,8 @@ pub struct GuiHandler {
|
|||
|
||||
resource_base_path: Option<AssetPath>,
|
||||
|
||||
top_ui: Option<Arc<dyn TopGui>>,
|
||||
tooltip_ui: Option<Arc<dyn TopGui>>,
|
||||
top_ui: Option<Arc<dyn TopLevelGui>>,
|
||||
tooltip_ui: Option<Arc<dyn TopLevelGui>>,
|
||||
|
||||
render_targets: TargetMode<RenderTarget>,
|
||||
command_buffers: TargetMode<Vec<CommandBufferState>>,
|
||||
|
@ -743,11 +743,13 @@ impl GuiHandler {
|
|||
|
||||
pub fn decline_topgui(&mut self, world: &mut World) -> Result<bool> {
|
||||
// workaround for unwanted borrowing behaviour inside decline function
|
||||
let opt_topgui = self.top_ui.as_ref().cloned();
|
||||
let opt_top_level_gui = self.top_ui.as_ref().cloned();
|
||||
|
||||
if let Some(topgui) = opt_topgui {
|
||||
topgui.decline(world)?;
|
||||
return Ok(true);
|
||||
if let Some(top_level_gui) = opt_top_level_gui {
|
||||
if let Some(top_gui) = top_level_gui.top_gui() {
|
||||
top_gui.decline(world)?;
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
|
@ -755,11 +757,13 @@ impl GuiHandler {
|
|||
|
||||
pub fn next_tab_topgui(&mut self, world: &mut World, second_level: bool) -> Result<bool> {
|
||||
// workaround for unwanted borrowing behaviour inside decline function
|
||||
let opt_topgui = self.top_ui.as_ref().cloned();
|
||||
let opt_top_level_gui = self.top_ui.as_ref().cloned();
|
||||
|
||||
if let Some(topgui) = opt_topgui {
|
||||
topgui.next_tab(world, second_level)?;
|
||||
return Ok(true);
|
||||
if let Some(top_level_gui) = opt_top_level_gui {
|
||||
if let Some(top_gui) = top_level_gui.top_gui() {
|
||||
top_gui.next_tab(world, second_level)?;
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
|
@ -767,11 +771,13 @@ impl GuiHandler {
|
|||
|
||||
pub fn previous_tab_topgui(&mut self, world: &mut World, second_level: bool) -> Result<bool> {
|
||||
// workaround for unwanted borrowing behaviour inside decline function
|
||||
let opt_topgui = self.top_ui.as_ref().cloned();
|
||||
let opt_top_level_gui = self.top_ui.as_ref().cloned();
|
||||
|
||||
if let Some(topgui) = opt_topgui {
|
||||
topgui.previous_tab(world, second_level)?;
|
||||
return Ok(true);
|
||||
if let Some(top_level_gui) = opt_top_level_gui {
|
||||
if let Some(top_gui) = top_level_gui.top_gui() {
|
||||
top_gui.previous_tab(world, second_level)?;
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
|
@ -857,12 +863,50 @@ impl GuiHandler {
|
|||
self.needs_update = true;
|
||||
}
|
||||
|
||||
pub fn set_top_gui(&mut self, top_gui: Option<Arc<dyn TopGui>>) {
|
||||
pub fn set_top_gui(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
top_gui: Option<Arc<dyn TopLevelGui>>,
|
||||
) -> Result<()> {
|
||||
match (&self.top_ui, &top_gui) {
|
||||
(Some(current), Some(incoming)) => {
|
||||
if !Arc::ptr_eq(current, incoming) {
|
||||
current.disable(world)?;
|
||||
}
|
||||
}
|
||||
(Some(current), None) => {
|
||||
current.disable(world)?;
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.top_ui = top_gui;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_tooltip(&mut self, tooltip: Option<Arc<dyn TopGui>>) {
|
||||
pub fn set_tooltip(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
tooltip: Option<Arc<dyn TopLevelGui>>,
|
||||
) -> Result<()> {
|
||||
match (&self.tooltip_ui, &tooltip) {
|
||||
(Some(current), Some(incoming)) => {
|
||||
if !Arc::ptr_eq(current, incoming) {
|
||||
current.disable(world)?;
|
||||
}
|
||||
}
|
||||
(Some(current), None) => {
|
||||
current.disable(world)?;
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.tooltip_ui = tooltip;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn add_callback<F: FnOnce(&mut World) -> Result<()> + Send + Sync + 'static>(
|
||||
|
|
|
@ -13,3 +13,4 @@ mod element_creator;
|
|||
mod gui_direction;
|
||||
mod mouse_button;
|
||||
pub mod prelude;
|
||||
pub mod state;
|
||||
|
|
|
@ -7,5 +7,6 @@ pub use super::gui_direction::GuiDirection;
|
|||
pub use super::gui_handler::prelude::*;
|
||||
pub use super::keyboard::Keyboard;
|
||||
pub use super::mouse_button::MouseButton;
|
||||
pub use super::state::*;
|
||||
pub use super::states::*;
|
||||
pub use super::tab_control::TabControl;
|
||||
|
|
307
src/state.rs
Normal file
307
src/state.rs
Normal file
|
@ -0,0 +1,307 @@
|
|||
use crate::prelude::*;
|
||||
use anyhow::{Result, anyhow};
|
||||
use ecs::World;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, RwLock, Weak};
|
||||
|
||||
/// Opaque handle for a State
|
||||
/// only used for updating callbacks
|
||||
#[derive(Clone)]
|
||||
pub struct StateHandle {
|
||||
state: Weak<State>,
|
||||
}
|
||||
|
||||
impl StateHandle {
|
||||
pub fn update<'a>(&self, update_type: StateUpdateType<'a>) -> Result<()> {
|
||||
self.state.upgrade().unwrap().update(update_type)
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<Button> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<Button>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<Grid> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<Grid>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<Label> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<Label>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<TextField> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<TextField>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<MultiLineTextField> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<MultiLineTextField>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<Icon> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<Icon>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<ProgressBar> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<ProgressBar>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct State {
|
||||
pub(crate) name: String,
|
||||
|
||||
pub(crate) top_level_gui: Arc<dyn TopLevelGui>,
|
||||
|
||||
pub(crate) on_activate: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||
pub(crate) on_deactivate: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||
|
||||
pub(crate) next_tab: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||
pub(crate) previous_tab: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||
pub(crate) decline: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub(crate) fn new<'a>(
|
||||
world: &mut World,
|
||||
name: &str,
|
||||
creation_type: CreationType<'a>,
|
||||
) -> Result<Arc<Self>> {
|
||||
let gui = match creation_type {
|
||||
CreationType::File(path) => GuiBuilder::new(world, path)?,
|
||||
CreationType::TopGui(top_gui) => top_gui,
|
||||
};
|
||||
|
||||
Ok(Arc::new(State {
|
||||
name: name.to_string(),
|
||||
|
||||
top_level_gui: gui,
|
||||
|
||||
on_activate: RwLock::new(None),
|
||||
on_deactivate: RwLock::new(None),
|
||||
|
||||
next_tab: RwLock::new(None),
|
||||
previous_tab: RwLock::new(None),
|
||||
decline: RwLock::new(None),
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn update<'a>(&self, update_type: StateUpdateType<'a>) -> Result<()> {
|
||||
match update_type {
|
||||
StateUpdateType::NextTab(next_tab) => self.set_next_tab(next_tab),
|
||||
StateUpdateType::PreviousTab(previous_tab) => self.set_previous_tab(previous_tab),
|
||||
StateUpdateType::Decline(decline) => self.set_decline(decline),
|
||||
StateUpdateType::OnActivate(oa) => self.set_on_activate(oa),
|
||||
StateUpdateType::OnDeactivate(oda) => self.set_on_deactivate(oda),
|
||||
StateUpdateType::ClickCallbacks(cbs) => {
|
||||
let functionality = self.functionality().ok_or(anyhow!(
|
||||
"State ({}) has no functionality implementation",
|
||||
self.name
|
||||
))?;
|
||||
|
||||
functionality.set_click_callbacks(cbs)?;
|
||||
}
|
||||
StateUpdateType::SelectCallbacks(cbs) => {
|
||||
let functionality = self.functionality().ok_or(anyhow!(
|
||||
"State ({}) has no functionality implementation",
|
||||
self.name
|
||||
))?;
|
||||
|
||||
functionality.set_select_callbacks(cbs)?;
|
||||
}
|
||||
StateUpdateType::CustomClickCallbacks(cbs) => {
|
||||
let functionality = self.functionality().ok_or(anyhow!(
|
||||
"State ({}) has no functionality implementation",
|
||||
self.name
|
||||
))?;
|
||||
|
||||
functionality.set_custom_callbacks(cbs)?;
|
||||
}
|
||||
StateUpdateType::VecCallbacks(vcbs) => {
|
||||
let functionality = self.functionality().ok_or(anyhow!(
|
||||
"State ({}) has no functionality implementation",
|
||||
self.name
|
||||
))?;
|
||||
|
||||
functionality.set_vec_callbacks(vcbs)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn set_on_activate(
|
||||
&self,
|
||||
on_activate: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||
) {
|
||||
*self.on_activate.write().unwrap() = on_activate;
|
||||
}
|
||||
|
||||
pub(crate) fn set_on_deactivate(
|
||||
&self,
|
||||
on_deactivate: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||
) {
|
||||
*self.on_deactivate.write().unwrap() = on_deactivate;
|
||||
}
|
||||
|
||||
pub(crate) fn set_previous_tab(
|
||||
&self,
|
||||
previous_tab: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||
) {
|
||||
*self.previous_tab.write().unwrap() = previous_tab;
|
||||
}
|
||||
|
||||
pub(crate) fn set_next_tab(
|
||||
&self,
|
||||
next_tab: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||
) {
|
||||
*self.next_tab.write().unwrap() = next_tab;
|
||||
}
|
||||
|
||||
pub(crate) fn set_decline(
|
||||
&self,
|
||||
decline: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||
) {
|
||||
*self.decline.write().unwrap() = decline;
|
||||
}
|
||||
}
|
||||
|
||||
impl TopGui for State {
|
||||
fn decline(&self, world: &mut World) -> Result<()> {
|
||||
match self.decline.read().unwrap().as_ref() {
|
||||
Some(decline) => {
|
||||
(decline)(world)?;
|
||||
}
|
||||
None => {
|
||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||
top_gui.decline(world)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn next_tab(&self, world: &mut World, second_level: bool) -> Result<()> {
|
||||
match self.next_tab.read().unwrap().as_ref() {
|
||||
Some(next_tab) => {
|
||||
(next_tab)(world)?;
|
||||
}
|
||||
None => {
|
||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||
top_gui.next_tab(world, second_level)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn previous_tab(&self, world: &mut World, second_level: bool) -> Result<()> {
|
||||
match self.previous_tab.read().unwrap().as_ref() {
|
||||
Some(previous_tab) => {
|
||||
(previous_tab)(world)?;
|
||||
}
|
||||
None => {
|
||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||
top_gui.previous_tab(world, second_level)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TopLevelGui for State {
|
||||
fn gui_traits(&self) -> &dyn GuiElementTraits {
|
||||
self.top_level_gui.gui_traits()
|
||||
}
|
||||
|
||||
fn top_gui(&self) -> Option<&dyn TopGui> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn elements(&self) -> Option<&HashMap<String, UiElement>> {
|
||||
self.top_level_gui.elements()
|
||||
}
|
||||
|
||||
fn functionality(&self) -> Option<&dyn Functionality> {
|
||||
self.top_level_gui.functionality()
|
||||
}
|
||||
|
||||
fn enable(&self, world: &mut World) -> Result<()> {
|
||||
self.top_level_gui.enable(world)?;
|
||||
|
||||
if let Some(activate) = self.on_activate.read().unwrap().as_ref() {
|
||||
(activate)(world)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn disable(&self, world: &mut World) -> Result<()> {
|
||||
self.top_level_gui.disable(world)?;
|
||||
|
||||
if let Some(deactivate) = self.on_deactivate.read().unwrap().as_ref() {
|
||||
(deactivate)(world)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<StateHandle> for Arc<State> {
|
||||
fn into(self) -> StateHandle {
|
||||
StateHandle {
|
||||
state: Arc::downgrade(&self),
|
||||
}
|
||||
}
|
||||
}
|
274
src/states.rs
274
src/states.rs
|
@ -7,7 +7,7 @@ use utilities::prelude::remove_life_time_mut;
|
|||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use std::sync::{Arc, Mutex, RwLock, Weak};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub trait FutureStateChange: Fn(&mut World) -> Result<()> + Send + Sync {
|
||||
fn clone_box<'a>(&self) -> Box<dyn 'a + FutureStateChange>
|
||||
|
@ -46,109 +46,6 @@ impl<'a> Clone for Box<dyn 'a + FutureStateChange> {
|
|||
}
|
||||
}
|
||||
|
||||
struct State {
|
||||
name: String,
|
||||
|
||||
top_level_gui: Arc<dyn TopLevelGui>,
|
||||
|
||||
on_activate: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||
on_deactivate: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||
|
||||
next_tab: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||
previous_tab: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||
decline: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||
}
|
||||
|
||||
/// Opaque handle for a State
|
||||
/// only used for updating callbacks
|
||||
#[derive(Clone)]
|
||||
pub struct StateHandle {
|
||||
state: Weak<State>,
|
||||
}
|
||||
|
||||
impl StateHandle {
|
||||
pub fn update<'a>(&self, update_type: StateUpdateType<'a>) -> Result<()> {
|
||||
self.state.upgrade().unwrap().update(update_type)
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<Button> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<Button>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<Grid> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<Grid>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<Label> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<Label>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<TextField> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<TextField>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<MultiLineTextField> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<MultiLineTextField>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<Icon> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<Icon>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetElement<ProgressBar> for StateHandle {
|
||||
fn element(&self, id: &str) -> Result<Arc<ProgressBar>> {
|
||||
let state = self.state.upgrade().unwrap();
|
||||
|
||||
match state.top_level_gui.elements() {
|
||||
Some(elements) => elements.element(id),
|
||||
None => panic!("state ({}) has no elements", state.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Update type
|
||||
pub enum StateUpdateType<'a> {
|
||||
/// Updates the callback which is executed on next tab event
|
||||
|
@ -312,14 +209,14 @@ impl States {
|
|||
}
|
||||
|
||||
// execute deactivate on old state
|
||||
old_state.deactivate(world)?;
|
||||
old_state.disable(world)?;
|
||||
}
|
||||
|
||||
// set new state, either no state or requested state
|
||||
match state {
|
||||
Some(state) => {
|
||||
state.activate(world)?;
|
||||
gui_handler.set_top_gui(Some(state.clone()));
|
||||
state.enable(world)?;
|
||||
gui_handler.set_top_gui(world, Some(state.clone()))?;
|
||||
|
||||
if logging {
|
||||
println!("Change UI State to {}", state.name);
|
||||
|
@ -328,7 +225,7 @@ impl States {
|
|||
*current = Some(state);
|
||||
}
|
||||
None => {
|
||||
gui_handler.set_top_gui(None);
|
||||
gui_handler.set_top_gui(world, None)?;
|
||||
|
||||
if logging {
|
||||
println!("Change UI State to None");
|
||||
|
@ -343,9 +240,7 @@ impl States {
|
|||
|
||||
/// Retrieve a StateHandle
|
||||
pub fn state_handle(&self, id: &str) -> Result<StateHandle> {
|
||||
Ok(StateHandle {
|
||||
state: Arc::downgrade(&self.get_state(id)?),
|
||||
})
|
||||
Ok(self.get_state(id)?.into())
|
||||
}
|
||||
|
||||
fn get_state(&self, id: &str) -> Result<Arc<State>> {
|
||||
|
@ -382,160 +277,3 @@ impl States {
|
|||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn new<'a>(
|
||||
world: &mut World,
|
||||
name: &str,
|
||||
creation_type: CreationType<'a>,
|
||||
) -> Result<Arc<Self>> {
|
||||
let gui = match creation_type {
|
||||
CreationType::File(path) => GuiBuilder::new(world, path)?,
|
||||
CreationType::TopGui(top_gui) => top_gui,
|
||||
};
|
||||
|
||||
Ok(Arc::new(State {
|
||||
name: name.to_string(),
|
||||
|
||||
top_level_gui: gui,
|
||||
|
||||
on_activate: RwLock::new(None),
|
||||
on_deactivate: RwLock::new(None),
|
||||
|
||||
next_tab: RwLock::new(None),
|
||||
previous_tab: RwLock::new(None),
|
||||
decline: RwLock::new(None),
|
||||
}))
|
||||
}
|
||||
|
||||
fn update<'a>(&self, update_type: StateUpdateType<'a>) -> Result<()> {
|
||||
match update_type {
|
||||
StateUpdateType::NextTab(next_tab) => self.set_next_tab(next_tab),
|
||||
StateUpdateType::PreviousTab(previous_tab) => self.set_previous_tab(previous_tab),
|
||||
StateUpdateType::Decline(decline) => self.set_decline(decline),
|
||||
StateUpdateType::OnActivate(oa) => self.set_on_activate(oa),
|
||||
StateUpdateType::OnDeactivate(oda) => self.set_on_deactivate(oda),
|
||||
StateUpdateType::ClickCallbacks(cbs) => {
|
||||
let functionality = self.functionality()?;
|
||||
functionality.set_click_callbacks(cbs)?;
|
||||
}
|
||||
StateUpdateType::SelectCallbacks(cbs) => {
|
||||
let functionality = self.functionality()?;
|
||||
functionality.set_select_callbacks(cbs)?;
|
||||
}
|
||||
StateUpdateType::CustomClickCallbacks(cbs) => {
|
||||
let functionality = self.functionality()?;
|
||||
functionality.set_custom_callbacks(cbs)?;
|
||||
}
|
||||
StateUpdateType::VecCallbacks(vcbs) => {
|
||||
let functionality = self.functionality()?;
|
||||
functionality.set_vec_callbacks(vcbs)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn functionality(&self) -> Result<&dyn Functionality> {
|
||||
match self.top_level_gui.functionality() {
|
||||
Some(functionality) => Ok(functionality),
|
||||
None => panic!("state ’{}' does not implement Functionality", &self.name),
|
||||
}
|
||||
}
|
||||
|
||||
fn activate(&self, world: &mut World) -> Result<()> {
|
||||
self.top_level_gui.enable(world)?;
|
||||
|
||||
if let Some(activate) = self.on_activate.read().unwrap().as_ref() {
|
||||
(activate)(world)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deactivate(&self, world: &mut World) -> Result<()> {
|
||||
self.top_level_gui.disable(world)?;
|
||||
|
||||
if let Some(deactivate) = self.on_deactivate.read().unwrap().as_ref() {
|
||||
(deactivate)(world)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_on_activate(
|
||||
&self,
|
||||
on_activate: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||
) {
|
||||
*self.on_activate.write().unwrap() = on_activate;
|
||||
}
|
||||
|
||||
fn set_on_deactivate(
|
||||
&self,
|
||||
on_deactivate: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||
) {
|
||||
*self.on_deactivate.write().unwrap() = on_deactivate;
|
||||
}
|
||||
|
||||
fn set_previous_tab(
|
||||
&self,
|
||||
previous_tab: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||
) {
|
||||
*self.previous_tab.write().unwrap() = previous_tab;
|
||||
}
|
||||
|
||||
fn set_next_tab(&self, next_tab: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>) {
|
||||
*self.next_tab.write().unwrap() = next_tab;
|
||||
}
|
||||
|
||||
fn set_decline(&self, decline: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>) {
|
||||
*self.decline.write().unwrap() = decline;
|
||||
}
|
||||
}
|
||||
|
||||
impl TopGui for State {
|
||||
fn decline(&self, world: &mut World) -> Result<()> {
|
||||
match self.decline.read().unwrap().as_ref() {
|
||||
Some(decline) => {
|
||||
(decline)(world)?;
|
||||
}
|
||||
None => {
|
||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||
top_gui.decline(world)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn next_tab(&self, world: &mut World, second_level: bool) -> Result<()> {
|
||||
match self.next_tab.read().unwrap().as_ref() {
|
||||
Some(next_tab) => {
|
||||
(next_tab)(world)?;
|
||||
}
|
||||
None => {
|
||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||
top_gui.next_tab(world, second_level)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn previous_tab(&self, world: &mut World, second_level: bool) -> Result<()> {
|
||||
match self.previous_tab.read().unwrap().as_ref() {
|
||||
Some(previous_tab) => {
|
||||
(previous_tab)(world)?;
|
||||
}
|
||||
None => {
|
||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||
top_gui.previous_tab(world, second_level)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue