use strum::EnumCount;
use crate::Application;
use crate::tree::NodeId;
use crate::interface::view;
use crate::interface::controller::{self, controls};
use super::impl_kind;
#[derive(Clone, Debug, Default)]
pub struct Switch {
pub state : State,
pub appearances : Appearances,
pub enter : Triggers,
pub exit : Triggers,
pub toggle : bool
}
impl_kind!(Switch);
#[derive(Clone, Debug, Default, Eq, PartialEq, EnumCount)]
pub enum State {
On,
#[default]
Off
}
#[derive(Clone, Debug, Default)]
pub struct Appearances (pub [(controller::Appearances, Option <String>); State::COUNT]);
#[derive(Clone, Debug, Default)]
pub struct Triggers (pub [Option <Trigger>; State::COUNT]);
#[derive(Clone, Debug)]
pub struct Trigger {
pub control_fun : controls::Fun <controls::button::Release>,
pub target : Option <NodeId>
}
#[derive(Clone, Default)]
pub struct Builder {
pub appearances : Appearances,
pub enter : Triggers,
pub exit : Triggers,
pub toggle : bool
}
impl Switch {
#[inline]
pub fn enter (&self) -> &Option <Trigger> {
&self.enter.0[self.state.clone() as usize]
}
#[inline]
pub fn exit (&self) -> &Option <Trigger> {
&self.exit.0[self.state.clone() as usize]
}
#[inline]
pub fn appearances (&self) -> &controller::Appearances {
&self.appearances.0[self.state.clone() as usize].0
}
#[inline]
pub fn label (&self) -> &Option <String> {
&self.appearances.0[self.state.clone() as usize].1
}
#[inline]
pub fn on (&mut self) -> (
Option <Trigger>,
(Option <Trigger>, controller::Appearances, Option <String>)
) {
if cfg!(debug_assertions) && self.state != State::Off {
log::debug!("switch on state not off: {:?}", self.state);
}
let from = self.exit().clone();
self.state = State::On;
let to = (self.enter().clone(), self.appearances().clone(), self.label().clone());
(from, to)
}
#[inline]
pub fn off (&mut self) -> (
Option <Trigger>,
(Option <Trigger>, controller::Appearances, Option <String>)
) {
if cfg!(debug_assertions) && self.state != State::On {
log::debug!("switch off state not on: {:?}", self.state);
}
let from = self.exit().clone();
self.state = State::Off;
let to = (self.enter().clone(), self.appearances().clone(), self.label().clone());
(from, to)
}
}
impl Builder {
#[inline]
pub const fn appearance (mut self,
state : (State, controller::State),
appearance : view::Appearance
) -> Self {
*self.appearances.appearance_mut (state) = appearance;
self
}
#[inline]
pub fn label (mut self, label : String) -> Self {
for (_, l) in self.appearances.0.iter_mut() {
*l = Some (label.clone());
}
self
}
#[inline]
pub fn label_on (mut self, label : String) -> Self {
self.appearances.0[State::On as usize].1 = Some (label);
self
}
#[inline]
pub fn label_off (mut self, label : String) -> Self {
self.appearances.0[State::Off as usize].1 = Some (label);
self
}
#[inline]
pub const fn enter (mut self, state : State, trigger : Trigger) -> Self {
*self.enter.get_mut (state) = Some (trigger);
self
}
#[inline]
pub const fn exit (mut self, state : State, trigger : Trigger) -> Self {
*self.exit.get_mut (state) = Some (trigger);
self
}
#[inline]
pub const fn style (mut self, state : (State, controller::State), style : view::Style)
-> Self
{
self.appearances.appearance_mut (state).style = Some(style);
self
}
#[inline]
pub fn style_default (mut self, state : (State, controller::State)) -> Self {
let style = Some (view::Style::default());
self.appearances.appearance_mut (state).style = style;
self
}
#[inline]
pub const fn sound (mut self, state : (State, controller::State), sound : view::Sound)
-> Self
{
self.appearances.appearance_mut (state).sound = Some (sound);
self
}
#[inline]
pub fn style_fg (mut self, state : (State, controller::State), color : view::Color)
-> Self
{
let style = &mut self.appearances.appearance_mut (state).style;
let mut s = style.take().unwrap_or_default();
s.fg = color;
*style = Some (s);
self
}
#[inline]
pub fn style_bg (mut self, state : (State, controller::State), color : view::Color)
-> Self
{
let appearance = &mut self.appearances.0[state.0 as usize].0.0[state.1 as usize];
let mut style = appearance.style.take().unwrap_or_default();
style.bg = color;
appearance.style = Some (style);
self
}
#[inline]
pub fn style_lo (mut self, state : (State, controller::State), color : view::Color)
-> Self
{
let appearance = &mut self.appearances.0[state.0 as usize].0.0[state.1 as usize];
let mut style = appearance.style.take().unwrap_or_default();
style.lo = color;
appearance.style = Some (style);
self
}
#[inline]
pub fn style_hi (mut self, state : (State, controller::State), color : view::Color)
-> Self
{
let appearance = &mut self.appearances.0[state.0 as usize].0.0[state.1 as usize];
let mut style = appearance.style.take().unwrap_or_default();
style.hi = color;
appearance.style = Some (style);
self
}
pub const fn toggle (mut self, toggle : bool) -> Self {
self.toggle = toggle;
self
}
#[inline]
pub fn build (self) -> Switch {
Switch {
appearances: self.appearances,
enter: self.enter,
exit: self.exit,
toggle: self.toggle,
.. Switch::default()
}
}
}
impl Appearances {
#[inline]
pub const fn appearance (&self, state : (State, controller::State))
-> &view::Appearance
{
self.0[state.0 as usize].0.get (state.1)
}
#[inline]
pub const fn appearance_mut (&mut self, state : (State, controller::State))
-> &mut view::Appearance
{
self.0[state.0 as usize].0.get_mut (state.1)
}
}
impl Triggers {
#[inline]
pub const fn get (&self, state : State) -> &Option <Trigger> {
&self.0[state as usize]
}
#[inline]
pub const fn get_mut (&mut self, state : State) -> &mut Option <Trigger> {
&mut self.0[state as usize]
}
}
impl Trigger {
#[inline]
pub fn new <A : Application> (control : controls::Button, target : Option <NodeId>)
-> Self
{
use controller::controls::Control;
let control_fun = control.fun::<A::ButtonControls>();
Trigger { control_fun, target }
}
}