gooey/interface/controller/controls/
button.rs

1use std::cell::RefCell;
2use serde_plain;
3use smallvec::SmallVec;
4use crate::interface::view::input;
5use crate::tree::NodeId;
6use crate::widget;
7
8use super::{Id, Nil};
9
10impl_control_builtin!{
11  Button <Release> {
12    ActivatePointer          => widget::frame::activate_pointer,
13    ButtonPush               => widget::button::push,
14    ButtonRelease            => widget::button::release,
15    FieldBackspace           => widget::field::backspace,
16    FormSubmitCallback       => widget::form::submit_callback,
17    FrameClose               => widget::frame::close,
18    FrameRefresh             => widget::frame::refresh,
19    FrameToggleOrientation   => widget::frame::toggle_orientation,
20    FrameFreeGrowWidth       => widget::frame::free::grow_width,
21    FrameFreeGrowHeight      => widget::frame::free::grow_height,
22    FrameFreeMoveDown        => widget::frame::free::move_down,
23    FrameFreeMoveLeft        => widget::frame::free::move_left,
24    FrameFreeMoveRight       => widget::frame::free::move_right,
25    FrameFreeMoveUp          => widget::frame::free::move_up,
26    FrameFreeShrinkHeight    => widget::frame::free::shrink_height,
27    FrameFreeShrinkWidth     => widget::frame::free::shrink_width,
28    FrameTiledDecreaseSize   => widget::frame::tiled::decrease_size,
29    FrameTiledIncreaseSize   => widget::frame::tiled::increase_size,
30    MenuNextItem             => widget::menu::next_item,
31    MenuPreviousItem         => widget::menu::previous_item,
32    MenuFirstItem            => widget::menu::first_item,
33    MenuLastItem             => widget::menu::last_item,
34    NumboxDecrease           => widget::numbox::decrease,
35    NumboxIncrease           => widget::numbox::increase,
36    NumboxDecrease10x        => widget::numbox::decrease_10x,
37    NumboxIncrease10x        => widget::numbox::increase_10x,
38    PlaybackLoop             => widget::playback::loop_,
39    PlaybackPlay             => widget::playback::play,
40    PlaybackReady            => widget::playback::ready,
41    TextboxScrollRight       => widget::textbox::scroll_right,
42    TextboxScrollLeft        => widget::textbox::scroll_left,
43    TextboxScrollUp          => widget::textbox::scroll_up,
44    TextboxScrollDown        => widget::textbox::scroll_down,
45    TextboxPageRight         => widget::textbox::page_right,
46    TextboxPageLeft          => widget::textbox::page_left,
47    TextboxPageUp            => widget::textbox::page_up,
48    TextboxPageDown          => widget::textbox::page_down
49  }
50}
51
52impl_control_serdes!{ Button }
53
54/// Argument type for button callbacks
55pub type Release = Option <RefCell <SmallVec <[(Button, NodeId); 1]>>>;
56
57/// Binds a button control to an input button
58#[derive(Clone, Debug, Eq, PartialEq)]
59pub struct Binding <E : Id <Button> = Nil> (pub Button, pub input::Button,
60  pub std::marker::PhantomData <E>);
61
62impl <E : Id <Button>> From <Binding <E>> for (input::Button, Button) {
63  fn from (Binding (control, input, _) : Binding <E>) -> Self {
64    (input, control)
65  }
66}
67
68impl <E : Id <Button>> From <(input::Button, Button)> for Binding <E> {
69  fn from ((input, control) : (input::Button, Button)) -> Self {
70    Binding (control, input, Default::default())
71  }
72}
73
74//
75// private
76//
77
78struct BindingVisitor <E : Id <Button> = Nil> (
79  std::marker::PhantomData <E>);
80
81impl <E : Id <Button>> serde::Serialize for Binding <E> {
82  fn serialize <S : serde::Serializer> (&self, serializer : S)
83    -> std::result::Result <S::Ok, S::Error>
84  {
85    use std::convert::TryFrom;
86    let control = if let Ok (builtin) = Builtin::try_from (self.0.clone()) {
87      serde_plain::to_string (&builtin).unwrap()
88    } else if let Ok (application) = E::try_from (self.0.clone()) {
89      serde_plain::to_string (&application).unwrap()
90    } else {
91      unreachable!()
92    };
93    let s = format!("{}: {}{}",
94      control, self.1.variant, self.1.modifiers.to_string());
95    serializer.serialize_str(&s)
96  }
97}
98
99impl <'de, E : Id <Button>> serde::de::Visitor <'de> for BindingVisitor <E> {
100  type Value = Binding <E>;
101  fn expecting (&self, formatter : &mut std::fmt::Formatter)
102    -> std::fmt::Result
103  {
104    formatter.write_str ("A control: button pair")
105  }
106  fn visit_str <ERR : serde::de::Error> (self, value : &str)
107    -> std::result::Result <Self::Value, ERR>
108  {
109    let control : Button = {
110      let s = value.split (':').next().unwrap();
111      if let Ok (builtin) = serde_plain::from_str::<Builtin> (s) {
112        builtin.into()
113      } else {
114         serde_plain::from_str::<E> (s).unwrap().into()
115      }
116    };
117    let button = {
118      use std::str::FromStr;
119      let mut iter = value.split (' ').skip (1).next().unwrap().split ('+');
120      let s        = iter.next().unwrap();
121      let variant  = input::button::Variant::from_str (&s).map_err (|err|{
122        log::error!(err:?, string=s; "error parsing button");
123        panic!("error parsing button string \"{s}\": {err}")
124      }).unwrap();
125      let mut modifiers = input::Modifiers::empty();
126      for modifier in iter {
127        match modifier.to_lowercase().as_str() {
128          "shift" => modifiers |= input::Modifiers::SHIFT,
129          "ctrl"  => modifiers |= input::Modifiers::CTRL,
130          "alt"   => modifiers |= input::Modifiers::ALT,
131          "super" => modifiers |= input::Modifiers::SUPER,
132          "any"   => modifiers |= input::Modifiers::ANY,
133          _ => return Err (
134            ERR::custom (format!("Unrecognized modifier: {:?}", modifier)))
135        }
136      }
137      input::Button { variant, modifiers }
138    };
139    Ok (Binding (control, button, Default::default()))
140  }
141}
142
143impl <'de, E : Id <Button>> serde::Deserialize <'de> for Binding <E> {
144  fn deserialize <D : serde::Deserializer <'de>> (deserializer : D)
145    -> std::result::Result <Self, D::Error>
146  {
147    deserializer.deserialize_str (BindingVisitor (Default::default()))
148  }
149}