use std::collections::{HashMap, HashSet}; use enum_map::EnumMap; use log::error; use deckster_shared::path::{KeyPath, KeyPosition, KnobPath, KnobPosition}; use deckster_shared::state::{Key, Knob}; use crate::model; use crate::runner::state; #[derive(Debug)] pub struct State { pub active_key_page_id: String, pub active_knob_page_id: String, pub active_touch_ids: HashSet, pub key_pages_by_id: HashMap, pub knob_pages_by_id: HashMap, } impl State { pub fn create(config: &model::config::Config) -> Self { let key_pages_by_id: HashMap<_, _> = config .key_pages_by_id .iter() .map(|(id, p)| state::KeyPage { id: id.clone(), keys_by_position: p .keys .iter() .map(|(position, k)| Key { path: KeyPath { page_id: p.id.clone(), position: *position, }, base_style: k.base_style.clone(), style: None, }) .map(|k| (k.path.position, k)) .collect(), }) .map(|p| (p.id.clone(), p)) .collect(); let knob_pages_by_id: HashMap<_, _> = config .knob_pages_by_id .iter() .map(|(id, p)| KnobPage { id: id.clone(), knobs_by_position: EnumMap::from_fn(|position| { let knob_config = &p.knobs[position]; Knob { path: KnobPath { page_id: p.id.clone(), position, }, base_style: knob_config.base_style.clone(), style: None, value: None, } }), }) .map(|p| (p.id.clone(), p)) .collect(); State { active_key_page_id: config.initial.key_page.clone(), active_knob_page_id: config.initial.knob_page.clone(), active_touch_ids: HashSet::new(), key_pages_by_id, knob_pages_by_id, } } pub fn mutate_key_for_command(&mut self, command_name: &'static str, path: &KeyPath, mutator: impl FnOnce(&mut Key) -> R) -> Option { match self.key_pages_by_id.get_mut(&path.page_id) { None => error!("Received {} command with invalid path.page_id: {}", command_name, &path.page_id), Some(key_page) => match key_page.keys_by_position.get_mut(&path.position) { None => error!("Received {} command with invalid path.position: {}", command_name, &path.position), Some(key) => return Some(mutator(key)), }, } None } pub fn mutate_knob_for_command(&mut self, command_name: &'static str, path: &KnobPath, mutator: impl FnOnce(&mut Knob) -> R) -> Option { match self.knob_pages_by_id.get_mut(&path.page_id) { None => error!("Received {} command with invalid path.page_id: {}", command_name, &path.page_id), Some(knob_page) => return Some(mutator(&mut knob_page.knobs_by_position[path.position])), } None } pub fn active_key_page(&self) -> &KeyPage { &self.key_pages_by_id[&self.active_key_page_id] } pub fn active_knob_page(&self) -> &KnobPage { &self.knob_pages_by_id[&self.active_knob_page_id] } } #[derive(Debug)] pub struct KeyPage { pub id: String, pub keys_by_position: HashMap, } #[derive(Debug)] pub struct KnobPage { pub id: String, pub knobs_by_position: EnumMap, }