kas_widgets/
event_config.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Drivers for configuration types
7
8use crate::{Button, CheckButton, ComboBox, SpinBox};
9use kas::config::{ConfigMsg, EventConfigMsg, MousePan};
10use kas::prelude::*;
11
12#[impl_self]
13mod EventConfig {
14    /// A widget for configuring event config
15    ///
16    /// This only needs to be added to a UI to be functional.
17    ///
18    /// Changes take effect immediately. A "Reset" button restores all
19    /// configuration to compiled (not saved) default values.
20    /// TODO: support undo and/or revert to saved values.
21    #[widget]
22    #[layout(grid! {
23        (0, 0) => "Hover delay:",
24        (1, 0) => self.menu_delay,
25
26        (0, 1) => "Menu delay:",
27        (1, 1) => self.menu_delay,
28
29        (0, 2) => "Touch-selection delay:",
30        (1, 2) => self.touch_select_delay,
31
32        (0, 3) => "Kinetic scrolling timeout:",
33        (1, 3) => self.kinetic_timeout,
34
35        (0, 4) => "Kinetic decay (relative):",
36        (1, 4) => self.kinetic_decay_mul,
37
38        (0, 5) => "Kinetic decay (absolute):",
39        (1, 5) => self.kinetic_decay_sub,
40
41        (0, 6) => "Kinetic decay when grabbed:",
42        (1, 6) => self.kinetic_grab_sub,
43
44        (0, 7) => "Scroll wheel distance:",
45        (1, 7) => self.scroll_dist_em,
46
47        (0, 8) => "Pan distance threshold:",
48        (1, 8) => self.pan_dist_thresh,
49
50        (0, 9) => "Mouse pan:",
51        (1, 9) => self.mouse_pan,
52
53        (0, 10) => "Mouse text pan:",
54        (1, 10) => self.mouse_text_pan,
55
56        (1, 11) => self.mouse_wheel_actions,
57
58        (1, 12) => self.mouse_nav_focus,
59
60        (1, 13) => self.touch_nav_focus,
61
62        (0, 14) => "Restore default values:",
63        (1, 14) => Button::label_msg("&Reset", EventConfigMsg::ResetToDefault),
64    })]
65    #[impl_default(EventConfig::new())]
66    pub struct EventConfig {
67        core: widget_core!(),
68        #[widget]
69        hover_delay: SpinBox<(), u32>,
70        #[widget]
71        menu_delay: SpinBox<(), u32>,
72        #[widget]
73        touch_select_delay: SpinBox<(), u32>,
74        #[widget]
75        kinetic_timeout: SpinBox<(), u32>,
76        #[widget]
77        kinetic_decay_mul: SpinBox<(), f32>,
78        #[widget]
79        kinetic_decay_sub: SpinBox<(), f32>,
80        #[widget]
81        kinetic_grab_sub: SpinBox<(), f32>,
82        #[widget]
83        scroll_dist_em: SpinBox<(), f32>,
84        #[widget]
85        pan_dist_thresh: SpinBox<(), f32>,
86        #[widget]
87        mouse_pan: ComboBox<(), MousePan>,
88        #[widget]
89        mouse_text_pan: ComboBox<(), MousePan>,
90        #[widget]
91        mouse_wheel_actions: CheckButton<()>,
92        #[widget]
93        mouse_nav_focus: CheckButton<()>,
94        #[widget]
95        touch_nav_focus: CheckButton<()>,
96    }
97
98    impl Events for Self {
99        type Data = ();
100
101        fn handle_messages(&mut self, cx: &mut EventCx, _: &()) {
102            if let Some(msg) = cx.try_pop() {
103                cx.change_config(ConfigMsg::Event(msg));
104            }
105        }
106    }
107
108    impl Self {
109        /// Construct an instance of the widget
110        pub fn new() -> Self {
111            let pan_options = [
112                ("&Never", MousePan::Never),
113                ("With &Alt key", MousePan::WithAlt),
114                ("With &Ctrl key", MousePan::WithCtrl),
115                ("Alwa&ys", MousePan::Always),
116            ];
117
118            EventConfig {
119                core: Default::default(),
120                hover_delay: SpinBox::new(0..=10_000, |cx, _| {
121                    cx.config().base().event.menu_delay_ms
122                })
123                .with_step(100)
124                .with_msg(EventConfigMsg::HoverDelay)
125                .with_unit("ms"),
126                menu_delay: SpinBox::new(0..=5_000, |cx, _| cx.config().base().event.menu_delay_ms)
127                    .with_step(50)
128                    .with_msg(EventConfigMsg::MenuDelay)
129                    .with_unit("ms"),
130                touch_select_delay: SpinBox::new(0..=5_000, |cx: &ConfigCx, _| {
131                    cx.config().base().event.touch_select_delay_ms
132                })
133                .with_step(50)
134                .with_msg(EventConfigMsg::TouchSelectDelay)
135                .with_unit("ms"),
136                kinetic_timeout: SpinBox::new(0..=500, |cx: &ConfigCx, _| {
137                    cx.config().base().event.kinetic_timeout_ms
138                })
139                .with_step(5)
140                .with_msg(EventConfigMsg::KineticTimeout)
141                .with_unit("ms"),
142                kinetic_decay_mul: SpinBox::new(0.0..=1.0, |cx: &ConfigCx, _| {
143                    cx.config().base().event.kinetic_decay_mul
144                })
145                .with_step(0.0625)
146                .with_msg(EventConfigMsg::KineticDecayMul),
147                kinetic_decay_sub: SpinBox::new(0.0..=1.0e4, |cx: &ConfigCx, _| {
148                    cx.config().base().event.kinetic_decay_sub
149                })
150                .with_step(10.0)
151                .with_msg(EventConfigMsg::KineticDecaySub),
152                kinetic_grab_sub: SpinBox::new(0.0..=1.0e4, |cx: &ConfigCx, _| {
153                    cx.config().base().event.kinetic_grab_sub
154                })
155                .with_step(5.0)
156                .with_msg(EventConfigMsg::KineticGrabSub),
157                scroll_dist_em: SpinBox::new(0.125..=125.0, |cx: &ConfigCx, _| {
158                    cx.config().base().event.scroll_dist_em
159                })
160                .with_step(0.125)
161                .with_msg(EventConfigMsg::ScrollDistEm)
162                .with_unit("em"),
163                pan_dist_thresh: SpinBox::new(0.25..=25.0, |cx: &ConfigCx, _| {
164                    cx.config().base().event.pan_dist_thresh
165                })
166                .with_step(0.25)
167                .with_msg(EventConfigMsg::PanDistThresh),
168                mouse_pan: ComboBox::new_msg(
169                    pan_options,
170                    |cx: &ConfigCx, _| cx.config().base().event.mouse_pan,
171                    EventConfigMsg::MousePan,
172                ),
173                mouse_text_pan: ComboBox::new_msg(
174                    pan_options,
175                    |cx: &ConfigCx, _| cx.config().base().event.mouse_text_pan,
176                    EventConfigMsg::MouseTextPan,
177                ),
178                mouse_wheel_actions: CheckButton::new_msg(
179                    "Mouse &wheel actions",
180                    |cx: &ConfigCx, _| cx.config().base().event.mouse_wheel_actions,
181                    EventConfigMsg::MouseWheelActions,
182                ),
183                mouse_nav_focus: CheckButton::new_msg(
184                    "&Mouse navigation focus",
185                    |cx: &ConfigCx, _| cx.config().base().event.mouse_nav_focus,
186                    EventConfigMsg::MouseNavFocus,
187                ),
188                touch_nav_focus: CheckButton::new_msg(
189                    "&Touchscreen navigation focus",
190                    |cx: &ConfigCx, _| cx.config().base().event.touch_nav_focus,
191                    EventConfigMsg::TouchNavFocus,
192                ),
193            }
194        }
195    }
196}