gooey/interface/controller/controls/
mod.rs

1//! Control callback and Id traits.
2//!
3//! An implementation of Control is defined for each type of Input. These are
4//! implemented as newtype structs with inner primitive `ReprType` payload.
5//!
6//! An implementation of Id is a serializable enum, parameterized by the Control
7//! type, and convertable to control `Fun` callbacks and to corresponding
8//! Control ReprTypes.
9//!
10//! To each implementation of Control is an associated Builtin Id type. Each
11//! Control type can be extended by the Application by defining a new Id type
12//! using the `extend_control!` macro. This macro will ensure that the resulting
13//! implementation does not overlap with the Builtin type in its conversion to a
14//! Control ReprType.
15
16use derive_builder::Builder;
17use sorted_vec::SortedSet;
18use serde::{Deserialize, Serialize};
19use crate::{interface, Tree};
20use crate::tree::NodeId;
21
22#[macro_use] mod macro_def;
23
24pub mod axis;
25pub mod button;
26pub mod motion;
27pub mod pointer;
28pub mod system;
29pub mod text;
30pub mod wheel;
31
32pub use self::axis::Axis;
33pub use self::button::Button;
34pub use self::motion::Motion;
35pub use self::pointer::Pointer;
36pub use self::system::System;
37pub use self::text::Text;
38pub use self::wheel::Wheel;
39
40pub use ControlsBuilder as Builder;
41
42/// A set of controls for looking up bindings
43#[derive(Clone, Debug, Default, Builder)]
44#[builder(pattern="owned", build_fn(skip), setter(strip_option))]
45pub struct Controls {
46  #[builder(default)]
47  pub buttons    : SortedSet <Button>,
48  #[builder(default)]
49  pub any_button : Option <Button>,
50  #[builder(default)]
51  pub system     : Option <System>,
52  #[builder(default)]
53  pub text       : Option <Text>,
54  #[builder(default)]
55  pub motion     : Option <Motion>,
56  #[builder(default)]
57  pub pointer    : Option <Pointer>
58  // TODO: more
59}
60
61/// A type of serializable names that map to control callbacks.
62///
63/// A type implementing Id is convertible with the `C:Control` type and maps to
64/// a control [`Fun`] taking the payload specified by the Control type.
65///
66/// This is the serializable type representing a control callback Fun used for
67/// saving and loading bindings.
68pub trait Id <C : Control> : Clone + Eq + PartialEq + Into <Fun <C::Payload>>
69  + Into <C> + std::convert::TryFrom <C, Error = C> + std::fmt::Debug
70  + serde::Serialize + serde::de::DeserializeOwned
71{ }
72
73/// A newtype wrapper for the parameterized control callback function type with
74/// payload type P.
75///
76/// This is a newtype so that `From <Control <A, ID>>` can be implemented.
77#[derive(Clone)]
78pub struct Fun <P> (pub fn (
79  &P,
80  &Tree <interface::Element>,
81  &NodeId,
82  &mut Vec <(NodeId, interface::Action)>
83));
84
85/// Primitive control index type alias
86pub type ReprType = u16;
87/// A primitive control callback index with associated payload and built-in
88/// control callback IDs
89pub trait Control : Clone + Sized + From <ReprType> + AsRef <ReprType>
90  + std::fmt::Debug
91{
92  type Payload;
93  type Builtin : Id <Self>;
94  fn fun <E : Id <Self>> (self) -> Fun <Self::Payload> {
95    use std::convert::TryFrom;
96    match Self::Builtin::try_from (self) {
97      Ok  (builtin) => builtin.into(),
98      Err (control) => match E::try_from (control) {
99        Ok  (extended) => extended.into(),
100        Err (_control) => unreachable!()
101      }
102    }
103  }
104}
105
106/// A nil type indicating no extra controls
107#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
108pub enum Nil {}
109impl <P> From <Nil> for Fun <P> {
110  fn from (_ : Nil) -> Self {
111    unreachable!()
112  }
113}
114
115impl <P> std::fmt::Debug for Fun <P> {
116  fn fmt (&self, f : &mut std::fmt::Formatter) -> Result <(), std::fmt::Error> {
117    write!(f, "Fun({:p})", &self.0)
118  }
119}
120
121impl ControlsBuilder {
122  pub fn new() -> Self {
123    ControlsBuilder {
124      buttons:    None,
125      any_button: None,
126      system:     None,
127      text:       None,
128      motion:     None,
129      pointer:    None
130    }
131  }
132
133  pub fn build (self) -> Controls {
134    Controls {
135      buttons:    self.buttons.unwrap_or_default(),
136      any_button: self.any_button.unwrap_or_default(),
137      system:     self.system.unwrap_or_default(),
138      text:       self.text.unwrap_or_default(),
139      motion:     self.motion.unwrap_or_default(),
140      pointer:    self.pointer.unwrap_or_default()
141    }
142  }
143}