gooey/interface/controller/controls/
button.rs1use 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
54pub type Release = Option <RefCell <SmallVec <[(Button, NodeId); 1]>>>;
56
57#[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
74struct 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}