Implement future state change
This commit is contained in:
parent
47163b097b
commit
ff076d016a
1 changed files with 69 additions and 35 deletions
104
src/states.rs
104
src/states.rs
|
@ -5,10 +5,7 @@ use assetpath::AssetPath;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use std::sync::{
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
atomic::{AtomicBool, Ordering::SeqCst},
|
|
||||||
Arc, Mutex, RwLock,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -160,11 +157,10 @@ pub struct States {
|
||||||
gui_handler: Arc<GuiHandler>,
|
gui_handler: Arc<GuiHandler>,
|
||||||
|
|
||||||
states: HashMap<String, Arc<State>>,
|
states: HashMap<String, Arc<State>>,
|
||||||
current_state: Mutex<Option<Arc<State>>>,
|
current_state: Arc<Mutex<Option<Arc<State>>>>,
|
||||||
|
|
||||||
control_top_gui: AtomicBool,
|
control_top_gui: bool,
|
||||||
|
log_state_change: bool,
|
||||||
log_state_change: AtomicBool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl States {
|
impl States {
|
||||||
|
@ -174,21 +170,22 @@ impl States {
|
||||||
gui_handler,
|
gui_handler,
|
||||||
|
|
||||||
states: HashMap::new(),
|
states: HashMap::new(),
|
||||||
current_state: Mutex::new(None),
|
current_state: Arc::new(Mutex::new(None)),
|
||||||
|
|
||||||
control_top_gui: AtomicBool::new(true),
|
control_top_gui: true,
|
||||||
|
log_state_change: false,
|
||||||
log_state_change: AtomicBool::new(false),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_logging(&self, logging: bool) {
|
pub fn change_logging(mut self, logging: bool) -> Self {
|
||||||
self.log_state_change.store(logging, SeqCst);
|
self.log_state_change = logging;
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a flag if states should set and unset top gui of the gui handler
|
/// Sets a flag if states should set and unset top gui of the gui handler
|
||||||
pub fn set_control_top_gui(&self, control_top_gui: bool) {
|
pub fn set_control_top_gui(mut self, control_top_gui: bool) -> Self {
|
||||||
self.control_top_gui.store(control_top_gui, SeqCst);
|
self.control_top_gui = control_top_gui;
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a single state
|
/// Adds a single state
|
||||||
|
@ -219,12 +216,28 @@ impl States {
|
||||||
///
|
///
|
||||||
/// * `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, id: impl Into<Option<&'b str>>) -> Result<()> {
|
||||||
let id = id.into();
|
Self::_set_state(
|
||||||
|
id.into().map(|id| self.get_state(id)).transpose()?,
|
||||||
|
&mut *self.current_state.lock().unwrap(),
|
||||||
|
if self.control_top_gui {
|
||||||
|
Some(self.gui_handler.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
self.log_state_change,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(old_state) = self.current_state.lock().unwrap().as_ref() {
|
fn _set_state(
|
||||||
|
state: Option<Arc<State>>,
|
||||||
|
current: &mut Option<Arc<State>>,
|
||||||
|
gui_handler: Option<Arc<GuiHandler>>,
|
||||||
|
logging: bool,
|
||||||
|
) -> Result<()> {
|
||||||
|
if let Some(old_state) = current {
|
||||||
// check if requested state is already in use
|
// check if requested state is already in use
|
||||||
if let Some(name) = id {
|
if let Some(new_state) = &state {
|
||||||
if name == old_state.name {
|
if new_state.name == old_state.name {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,32 +247,30 @@ impl States {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set new state, either no state or requested state
|
// set new state, either no state or requested state
|
||||||
match id {
|
match state {
|
||||||
Some(name) => {
|
Some(state) => {
|
||||||
let state: Arc<State> = self.get_state(name)?;
|
|
||||||
|
|
||||||
state.activate()?;
|
state.activate()?;
|
||||||
|
|
||||||
if self.control_top_gui.load(SeqCst) {
|
if let Some(gui_handler) = gui_handler {
|
||||||
self.gui_handler.set_top_gui(Some(state.clone()));
|
gui_handler.set_top_gui(Some(state.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
*self.current_state.lock().unwrap() = Some(state);
|
if logging {
|
||||||
|
println!("Change UI State to {}", state.name);
|
||||||
if self.log_state_change.load(SeqCst) {
|
|
||||||
println!("Change UI State to {}", name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*current = Some(state);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if self.control_top_gui.load(SeqCst) {
|
if let Some(gui_handler) = gui_handler {
|
||||||
self.gui_handler.set_top_gui(None);
|
gui_handler.set_top_gui(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
*self.current_state.lock().unwrap() = None;
|
if logging {
|
||||||
|
|
||||||
if self.log_state_change.load(SeqCst) {
|
|
||||||
println!("Change UI State to None");
|
println!("Change UI State to None");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*current = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,6 +290,29 @@ impl States {
|
||||||
None => Err(anyhow::Error::msg(format!("UiState not found: {}", id))),
|
None => Err(anyhow::Error::msg(format!("UiState not found: {}", id))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn future_state_change<'b>(
|
||||||
|
&self,
|
||||||
|
id: impl Into<Option<&'b str>>,
|
||||||
|
) -> Result<impl Fn() -> Result<()>> {
|
||||||
|
let state = id.into().map(|id| self.get_state(id)).transpose()?;
|
||||||
|
let current_state = self.current_state.clone();
|
||||||
|
let gui_handler = if self.control_top_gui {
|
||||||
|
Some(self.gui_handler.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let logging = self.log_state_change;
|
||||||
|
|
||||||
|
Ok(move || {
|
||||||
|
Self::_set_state(
|
||||||
|
state.clone(),
|
||||||
|
&mut *current_state.lock().unwrap(),
|
||||||
|
gui_handler.clone(),
|
||||||
|
logging,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
|
|
Loading…
Reference in a new issue