1use lazy_static::lazy_static;
20
21use crate::prelude::*;
22
23pub use self::builder::ButtonBuilder as Builder;
24
25pub type Button <'element> = Widget <'element,
26 controller::component::Switch, model::Component, view::Component>;
27
28lazy_static!{
33 pub static ref CONTROLS : Controls = controls::Builder::new()
34 .buttons (vec![
35 controls::button::Builtin::ButtonPush,
36 controls::button::Builtin::ButtonRelease
37 ].into_iter().map (Into::into).collect::<Vec <_>>().into())
38 .build();
39}
40
41pub fn push (
43 release : &controls::button::Release,
44 elements : &Tree <Element>,
45 frame_id : &NodeId,
46 action_buffer : &mut Vec <(NodeId, Action)>
47) {
48 log::trace!("push...");
49 let frame = elements.get_element (frame_id);
50 let mut frame_children = elements.children_ids (frame_id).unwrap();
51 let button_id = frame_children.next().unwrap();
52 let label_id = frame_children
53 .filter (|node_id| Textbox::try_get (elements, node_id).is_ok())
54 .next();
55 let Widget (switch, _, _) = Button::try_get (elements, button_id).unwrap();
56 let toggle = switch.toggle;
57 if toggle && switch.state == switch::State::On {
58 return self::release (&None, elements, frame_id, action_buffer)
59 }
60 let mut switch = switch.clone();
61 let (exit, (enter, appearances, label)) = switch.on();
62 let update_switch = Box::new (
66 |controller : &mut Controller| controller.component = switch.into());
67 action_buffer
68 .push ((button_id.clone(), Action::ModifyController (update_switch)));
69 let appearance = Appearance {
71 sound: None, .. appearances.get (frame.controller.state.clone()).clone()
72 };
73 let update_controller = Box::new (
74 |controller : &mut Controller| controller.appearances = appearances);
75 let update_view = Box::new (
76 |view : &mut View| view.appearance = appearance);
77 action_buffer
78 .push ((frame_id.clone(), Action::ModifyController (update_controller)));
79 action_buffer
80 .push ((frame_id.clone(), Action::ModifyView (update_view)));
81 if let Some (trigger) = exit {
83 let target = trigger.target.as_ref().unwrap_or (button_id);
84 trigger.control_fun.0 (release, elements, target, action_buffer)
85 }
86 if let Some (textbox_id) = label_id {
88 action_buffer.push ((textbox_id.clone(), Action::Destroy))
89 }
90 if let Some (label) = label {
92 let textbox =
93 textbox::WithFrameBuilder::<application::Default>::new (
94 &elements, frame_id
95 ) .text (label)
96 .build_element();
97 action_buffer.push ((frame_id.clone(),
98 Action::create_singleton (textbox, CreateOrder::Append)))
99 }
100 if let Some (trigger) = enter {
102 let target = trigger.target.as_ref().unwrap_or (button_id);
103 trigger.control_fun.0 (release, elements, target, action_buffer)
104 }
105 if !toggle {
106 if let Some (release) = release {
108 release.borrow_mut().push (
109 (controls::button::Builtin::ButtonRelease.into(), frame_id.clone()));
110 }
111 }
112 log::trace!("...push");
113}
114
115pub fn release (
117 _ : &controls::button::Release,
118 elements : &Tree <Element>,
119 frame_id : &NodeId,
120 action_buffer : &mut Vec <(NodeId, Action)>
121) {
122 log::trace!("release...");
123 let frame = elements.get_element (frame_id);
124 let mut frame_children = elements.children_ids (frame_id).unwrap();
125 let button_id = frame_children.next().unwrap();
126 let label_id = frame_children
127 .filter (|node_id| Textbox::try_get (elements, node_id).is_ok())
128 .next();
129 let Widget (switch, _, _) = Button::try_get (elements, button_id).unwrap();
130 let mut switch = switch.clone();
131 let (exit, (enter, appearances, label)) = switch.off();
132 if let Some (trigger) = exit {
134 let target = trigger.target.as_ref().unwrap_or (button_id);
135 trigger.control_fun.0 (&None, elements, target, action_buffer)
136 }
137 if let Some (textbox_id) = label_id {
139 action_buffer.push ((textbox_id.clone(), Action::Destroy))
140 }
141 if let Some (label) = label {
143 let textbox =
144 textbox::WithFrameBuilder::<application::Default>::new (
145 &elements, frame_id
146 ) .text (label)
147 .build_element();
148 action_buffer.push ((frame_id.clone(),
149 Action::create_singleton (textbox, CreateOrder::Append)))
150 }
151 if let Some (trigger) = enter {
153 let target = trigger.target.as_ref().unwrap_or (button_id);
154 trigger.control_fun.0 (&None, elements, target, action_buffer)
155 }
156 let update_switch = Box::new (
158 |controller : &mut Controller| controller.component = switch.into());
159 action_buffer
160 .push ((button_id.clone(), Action::ModifyController (update_switch)));
161 let appearance = view::Appearance {
163 sound: None,
164 .. appearances.get (frame.controller.state.clone()).clone()
165 };
166 let update_controller = Box::new (
167 |controller : &mut Controller| controller.appearances = appearances);
168 let update_view = Box::new (
169 |view : &mut View| view.appearance = appearance);
170 action_buffer
171 .push ((frame_id.clone(), Action::ModifyController (update_controller)));
172 action_buffer
173 .push ((frame_id.clone(), Action::ModifyView (update_view)));
174 log::trace!("...release");
175}
176
177mod builder {
182 use derive_builder::Builder;
183 use crate::prelude::*;
184
185 #[derive(Builder)]
186 #[builder(pattern="owned", build_fn(private), setter(strip_option))]
187 pub struct Button <'a, A : Application> {
188 elements : &'a Tree <Element>,
189 parent_id : &'a NodeId,
190 #[builder(default)]
191 bindings : Option <&'a controller::Bindings <A>>,
192 #[builder(default)]
193 callback_id : Option <application::CallbackId>,
194 #[builder(default)]
195 controls : Option <controller::Controls>,
196 #[builder(default)]
197 frame_layout : controller::component::Layout,
198 #[builder(default)]
199 frame_border : Option <view::Border>,
200 #[builder(default)]
201 model_data : Option <model::Component>,
202 #[builder(default)]
203 switch : controller::component::Switch
204 }
205
206 impl <'a, A : Application> ButtonBuilder <'a, A> {
207 pub fn new (elements : &'a Tree <Element>, parent_id : &'a NodeId) -> Self {
208 ButtonBuilder {
209 elements: Some (elements),
210 parent_id: Some (parent_id),
211 bindings: None,
212 callback_id: None,
213 controls: None,
214 frame_border: None,
215 frame_layout: None,
216 model_data: None,
217 switch: None
218 }
219 }
220 }
221
222 impl <'a, A : Application> BuildActions for ButtonBuilder <'a, A> {
223 fn build_actions (self) -> Vec<(NodeId, Action)> {
228 use std::convert::TryInto;
229 use crate::tree::InsertBehavior;
230 log::trace!("build actions...");
231 let Button {
232 elements, parent_id, bindings, callback_id, controls, frame_border,
233 frame_layout, model_data, switch
234 } = self.build()
235 .map_err(|err| log::error!("button builder error: {:?}", err)).unwrap();
236 let bindings_empty = Bindings::empty();
237 let bindings = bindings.unwrap_or (&bindings_empty);
238 let mut out = vec![];
239 let (mut subtree, order) = {
240 let mut actions = {
241 let mut frame = frame::Builder::new (elements, parent_id)
242 .appearances (switch.appearances().clone())
243 .bindings (bindings)
244 .layout (frame_layout);
245 set_option!(frame, border, frame_border);
246 frame.build_actions()
247 };
248 out.extend (actions.drain (1..));
249 debug_assert_eq!(actions.len(), 1);
250 actions.pop().unwrap().1.try_into().unwrap()
251 };
252 let frame_id = subtree.root_node_id().unwrap().clone();
253 subtree.get_mut (&frame_id).unwrap().data_mut().controller.add_bindings (
254 &bindings.get_bindings (controls.as_ref().unwrap_or (&super::CONTROLS))
255 );
256 let label = switch.label().clone();
257 let button = {
258 let controller = {
259 let mut controller = Controller::default();
260 controller.component = switch.into();
261 controller.focus_top = false;
262 controller
263 };
264 let model = {
265 let component = model_data.unwrap_or_else (Default::default);
266 Model { callback_id, component }
267 };
268 Element::new ("Button".to_string(), controller, model, View::default())
269 };
270 let _ = subtree
271 .insert (Node::new (button), InsertBehavior::UnderNode (&frame_id))
272 .unwrap();
273 if let Some (label) = label {
274 let textbox = textbox::WithFrameBuilder::<A>::new (
275 &subtree, &frame_id
276 ) .text (label)
277 .build_element();
278 let _ = subtree
279 .insert (Node::new (textbox), InsertBehavior::UnderNode (&frame_id))
280 .unwrap();
281 };
282 out.push ((parent_id.clone(), Action::Create (subtree, order)));
283 log::trace!("...build actions");
284 out
285 }
286 }
287}