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 -> 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!("{}: {}{}", control, self.1.variant, self.1.modifiers);
94 serializer.serialize_str(&s)
95 }
96}
97
98impl <E : Id <Button>> serde::de::Visitor <'_> for BindingVisitor <E> {
99 type Value = Binding <E>;
100 fn expecting (&self, formatter : &mut std::fmt::Formatter) -> std::fmt::Result {
101 formatter.write_str ("A control: button pair")
102 }
103 fn visit_str <ERR : serde::de::Error> (self, v : &str) -> Result <Self::Value, ERR> {
104 let control : Button = {
105 let s = v.split (':').next().unwrap();
106 if let Ok (builtin) = serde_plain::from_str::<Builtin> (s) {
107 builtin.into()
108 } else {
109 serde_plain::from_str::<E> (s).unwrap().into()
110 }
111 };
112 let button = {
113 use std::str::FromStr;
114 let mut iter = v.split (' ').nth (1).unwrap().split ('+');
115 let s = iter.next().unwrap();
116 let variant = input::button::Variant::from_str (s).map_err (|err|{
117 log::error!(err:?, string=s; "error parsing button");
118 panic!("error parsing button string \"{s}\": {err}")
119 }).unwrap();
120 let mut modifiers = input::Modifiers::empty();
121 for modifier in iter {
122 match modifier.to_lowercase().as_str() {
123 "shift" => modifiers |= input::Modifiers::SHIFT,
124 "ctrl" => modifiers |= input::Modifiers::CTRL,
125 "alt" => modifiers |= input::Modifiers::ALT,
126 "super" => modifiers |= input::Modifiers::SUPER,
127 "any" => modifiers |= input::Modifiers::ANY,
128 _ => return Err (
129 ERR::custom (format!("Unrecognized modifier: {modifier:?}")))
130 }
131 }
132 input::Button { variant, modifiers }
133 };
134 Ok (Binding (control, button, Default::default()))
135 }
136}
137
138impl <'de, E : Id <Button>> serde::Deserialize <'de> for Binding <E> {
139 fn deserialize <D : serde::Deserializer <'de>> (deserializer : D)
140 -> Result <Self, D::Error>
141 {
142 deserializer.deserialize_str (BindingVisitor (Default::default()))
143 }
144}