Skip to main content

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        row!["Hover delay:", self.hover_delay],
24        row!["Menu delay:", self.menu_delay],
25        row!["Touch-selection delay:", self.touch_select_delay],
26        row!["Kinetic scrolling timeout:", self.kinetic_timeout],
27        row!["Kinetic decay (relative):", self.kinetic_decay_mul],
28        row!["Kinetic decay (absolute):", self.kinetic_decay_sub],
29        row!["Kinetic decay when grabbed:", self.kinetic_grab_sub],
30        row!["Scroll wheel distance:", self.scroll_dist_em],
31        row!["Pan distance threshold:", self.pan_dist_thresh],
32        row!["Double-click distance threshold:", self.double_click_dist_thresh],
33        row!["Mouse pan:", self.mouse_pan],
34        row!["Mouse text pan:", self.mouse_text_pan],
35        row![_, self.mouse_wheel_actions],
36        row![_, self.mouse_nav_focus],
37        row![_, self.touch_nav_focus],
38        row![
39            "Restore default values:",
40            Button::label_msg("&Reset", EventConfigMsg::ResetToDefault),
41        ],
42    })]
43    #[impl_default(EventConfig::new())]
44    pub struct EventConfig {
45        core: widget_core!(),
46        #[widget]
47        hover_delay: SpinBox<(), u32>,
48        #[widget]
49        menu_delay: SpinBox<(), u32>,
50        #[widget]
51        touch_select_delay: SpinBox<(), u32>,
52        #[widget]
53        kinetic_timeout: SpinBox<(), u32>,
54        #[widget]
55        kinetic_decay_mul: SpinBox<(), f32>,
56        #[widget]
57        kinetic_decay_sub: SpinBox<(), f32>,
58        #[widget]
59        kinetic_grab_sub: SpinBox<(), f32>,
60        #[widget]
61        scroll_dist_em: SpinBox<(), f32>,
62        #[widget]
63        pan_dist_thresh: SpinBox<(), f32>,
64        #[widget]
65        double_click_dist_thresh: SpinBox<(), f32>,
66        #[widget]
67        mouse_pan: ComboBox<(), MousePan>,
68        #[widget]
69        mouse_text_pan: ComboBox<(), MousePan>,
70        #[widget]
71        mouse_wheel_actions: CheckButton<()>,
72        #[widget]
73        mouse_nav_focus: CheckButton<()>,
74        #[widget]
75        touch_nav_focus: CheckButton<()>,
76    }
77
78    impl Events for Self {
79        type Data = ();
80
81        fn handle_messages(&mut self, cx: &mut EventCx, _: &()) {
82            if let Some(msg) = cx.try_pop() {
83                cx.change_config(ConfigMsg::Event(msg));
84            }
85        }
86    }
87
88    impl Self {
89        /// Construct an instance of the widget
90        pub fn new() -> Self {
91            let pan_options = [
92                ("&Never", MousePan::Never),
93                ("With &Alt key", MousePan::WithAlt),
94                ("With &Ctrl key", MousePan::WithCtrl),
95                ("Alwa&ys", MousePan::Always),
96            ];
97
98            EventConfig {
99                core: Default::default(),
100                hover_delay: SpinBox::new(0..=10_000, |cx, _| {
101                    cx.config().base().event.menu_delay_ms
102                })
103                .with_step(100)
104                .with_msg(EventConfigMsg::HoverDelay)
105                .with_unit("ms"),
106                menu_delay: SpinBox::new(0..=5_000, |cx, _| cx.config().base().event.menu_delay_ms)
107                    .with_step(50)
108                    .with_msg(EventConfigMsg::MenuDelay)
109                    .with_unit("ms"),
110                touch_select_delay: SpinBox::new(0..=5_000, |cx: &ConfigCx, _| {
111                    cx.config().base().event.touch_select_delay_ms
112                })
113                .with_step(50)
114                .with_msg(EventConfigMsg::TouchSelectDelay)
115                .with_unit("ms"),
116                kinetic_timeout: SpinBox::new(0..=500, |cx: &ConfigCx, _| {
117                    cx.config().base().event.kinetic_timeout_ms
118                })
119                .with_step(5)
120                .with_msg(EventConfigMsg::KineticTimeout)
121                .with_unit("ms"),
122                kinetic_decay_mul: SpinBox::new(0.0..=1.0, |cx: &ConfigCx, _| {
123                    cx.config().base().event.kinetic_decay_mul
124                })
125                .with_step(0.0625)
126                .with_msg(EventConfigMsg::KineticDecayMul),
127                kinetic_decay_sub: SpinBox::new(0.0..=1.0e4, |cx: &ConfigCx, _| {
128                    cx.config().base().event.kinetic_decay_sub
129                })
130                .with_step(10.0)
131                .with_msg(EventConfigMsg::KineticDecaySub),
132                kinetic_grab_sub: SpinBox::new(0.0..=1.0e4, |cx: &ConfigCx, _| {
133                    cx.config().base().event.kinetic_grab_sub
134                })
135                .with_step(5.0)
136                .with_msg(EventConfigMsg::KineticGrabSub),
137                scroll_dist_em: SpinBox::new(0.125..=125.0, |cx: &ConfigCx, _| {
138                    cx.config().base().event.scroll_dist_em
139                })
140                .with_step(0.125)
141                .with_msg(EventConfigMsg::ScrollDistEm)
142                .with_unit("em"),
143                pan_dist_thresh: SpinBox::new(0.25..=25.0, |cx: &ConfigCx, _| {
144                    cx.config().base().event.pan_dist_thresh
145                })
146                .with_step(0.25)
147                .with_msg(EventConfigMsg::PanDistThresh)
148                .with_unit("px"),
149                double_click_dist_thresh: SpinBox::new(0.25..=16.0, |cx: &ConfigCx, _| {
150                    cx.config().base().event.double_click_dist_thresh
151                })
152                .with_step(0.25)
153                .with_msg(EventConfigMsg::DoubleClickDistThresh)
154                .with_unit("px"),
155                mouse_pan: ComboBox::new_msg(
156                    pan_options,
157                    |cx: &ConfigCx, _| cx.config().base().event.mouse_pan,
158                    EventConfigMsg::MousePan,
159                ),
160                mouse_text_pan: ComboBox::new_msg(
161                    pan_options,
162                    |cx: &ConfigCx, _| cx.config().base().event.mouse_text_pan,
163                    EventConfigMsg::MouseTextPan,
164                ),
165                mouse_wheel_actions: CheckButton::new_msg(
166                    "Mouse &wheel actions",
167                    |cx: &ConfigCx, _| cx.config().base().event.mouse_wheel_actions,
168                    EventConfigMsg::MouseWheelActions,
169                ),
170                mouse_nav_focus: CheckButton::new_msg(
171                    "&Mouse navigation focus",
172                    |cx: &ConfigCx, _| cx.config().base().event.mouse_nav_focus,
173                    EventConfigMsg::MouseNavFocus,
174                ),
175                touch_nav_focus: CheckButton::new_msg(
176                    "&Touchscreen navigation focus",
177                    |cx: &ConfigCx, _| cx.config().base().event.touch_nav_focus,
178                    EventConfigMsg::TouchNavFocus,
179                ),
180            }
181        }
182    }
183}