mirror of https://github.com/wayvr-org/wayvr.git
add disabled state for checkboxes and apply to enable swipe to type
This commit is contained in:
parent
ad89b44db2
commit
13d63b00fd
|
|
@ -230,6 +230,7 @@
|
|||
"NEED_TO_DOWNLOAD_MODELS": "The swipe-to-type model needs to be downloaded.\nDownload it now?",
|
||||
"MODELS_DOWNLOADED": "Model downloaded",
|
||||
"MODELS_NOT_DOWNLOADED": "Model not downloaded",
|
||||
"MODEL_REQUIRED_TO_ENABLE": "Download the swipe-to-type model to enable this option.",
|
||||
"REMOVE_MODELS": "Remove swipe to type model",
|
||||
"DOWNLOAD_MODELS": "Download swipe to type model",
|
||||
"DOWNLOAD_MODELS_HELP": "Swipe to type only works on qwerty layout keyboards"
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ impl SettingType {
|
|||
Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"),
|
||||
Self::KeyboardMiddleClick => Ok("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK"),
|
||||
Self::KeyboardSoundEnabled => Ok("APP_SETTINGS.KEYBOARD_SOUND_ENABLED"),
|
||||
Self::KeyboardSwipeToTypeEnabled => Ok("APP_SETTINGS.KEYBOARD_SWIPE_TYPE_ENABLED"),
|
||||
Self::KeyboardSwipeToTypeEnabled => Ok("APP_SETTINGS.KEYBOARD_SWIPE_TO_TYPE_ENABLED"),
|
||||
Self::Language => Ok("APP_SETTINGS.LANGUAGE"),
|
||||
Self::LeftHandedMouse => Ok("APP_SETTINGS.LEFT_HANDED_MOUSE"),
|
||||
Self::LongPressDuration => Ok("APP_SETTINGS.LONG_PRESS_DURATION"),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ use std::path::PathBuf;
|
|||
use std::rc::Rc;
|
||||
|
||||
use wgui::{
|
||||
components::button::{ButtonClickEvent, ComponentButton},
|
||||
components::{
|
||||
button::{ButtonClickEvent, ComponentButton},
|
||||
checkbox::ComponentCheckbox,
|
||||
},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::WidgetID,
|
||||
|
|
@ -18,7 +21,10 @@ use crate::{
|
|||
frontend::FrontendTasks,
|
||||
tab::settings::{
|
||||
SettingType, SettingsMountParams, SettingsTab, TabNameEnum, Task as ParentTask, horiz_cell,
|
||||
macros::{MacroParams, options_category, options_checkbox, options_range_f32},
|
||||
mount_requires_restart,
|
||||
macros::{
|
||||
MacroParams, options_category, options_checkbox, options_range_f32,
|
||||
},
|
||||
},
|
||||
util::{
|
||||
popup_manager::PopupHolder,
|
||||
|
|
@ -206,7 +212,7 @@ impl State {
|
|||
if par.feats.swipe_to_type {
|
||||
swipe_type_models_button(par.mp, c)?;
|
||||
}
|
||||
options_checkbox(par.mp, c, SettingType::KeyboardSwipeToTypeEnabled)?;
|
||||
swipe_type_enabled_checkbox(par.mp, c)?;
|
||||
options_checkbox(par.mp, c, SettingType::NotificationsEnabled)?;
|
||||
options_checkbox(par.mp, c, SettingType::NotificationsSoundEnabled)?;
|
||||
options_checkbox(par.mp, c, SettingType::KeyboardSoundEnabled)?;
|
||||
|
|
@ -494,5 +500,61 @@ fn swipe_type_models_button(mp: &mut MacroParams, parent: WidgetID) -> anyhow::R
|
|||
}
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn swipe_type_enabled_checkbox(mp: &mut MacroParams, parent: WidgetID) -> anyhow::Result<()> {
|
||||
let id = mp.idx.to_string();
|
||||
mp.idx += 1;
|
||||
|
||||
let setting = SettingType::KeyboardSwipeToTypeEnabled;
|
||||
|
||||
// cannot enable swipe-to-type until the model is downloaded
|
||||
let model_downloaded = swwipe_type_model_downloaded().unwrap_or_default();
|
||||
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("id", &id);
|
||||
|
||||
match setting.get_translation() {
|
||||
Ok(translation) => params.insert("translation", translation),
|
||||
Err(raw_text) => params.insert("text", raw_text),
|
||||
};
|
||||
|
||||
let tooltip = if model_downloaded {
|
||||
setting.get_tooltip()
|
||||
} else {
|
||||
Some("APP_SETTINGS.SWIPE_TYPE.MODEL_REQUIRED_TO_ENABLE")
|
||||
};
|
||||
if let Some(tooltip) = tooltip {
|
||||
params.insert("tooltip", tooltip);
|
||||
}
|
||||
|
||||
let checked = if *setting.mut_bool(mp.config) { "1" } else { "0" };
|
||||
params.insert("checked", checked);
|
||||
|
||||
let id_cell = horiz_cell(mp.layout, parent)?;
|
||||
|
||||
mp.parser_state
|
||||
.instantiate_template(mp.doc_params, "CheckBoxSetting", mp.layout, id_cell, params)?;
|
||||
|
||||
if setting.requires_restart() {
|
||||
mount_requires_restart(mp.layout, id_cell)?;
|
||||
}
|
||||
|
||||
let checkbox = mp.parser_state.fetch_component_as::<ComponentCheckbox>(&id)?;
|
||||
|
||||
if !model_downloaded {
|
||||
let mut common = mp.layout.common();
|
||||
checkbox.set_disabled(&mut common, true);
|
||||
}
|
||||
|
||||
checkbox.on_toggle(Box::new({
|
||||
let tasks = mp.tasks.clone();
|
||||
move |_common, e| {
|
||||
tasks.push(ParentTask::UpdateBool(setting, e.checked));
|
||||
Ok(())
|
||||
}
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -66,6 +66,7 @@ struct State {
|
|||
checked: bool,
|
||||
hovered: bool,
|
||||
down: bool,
|
||||
disabled: bool,
|
||||
on_toggle: Option<CheckboxToggleCallback>,
|
||||
self_ref: Weak<ComponentCheckbox>,
|
||||
active_tooltip: Option<Rc<ComponentTooltip>>,
|
||||
|
|
@ -99,6 +100,32 @@ pub struct ComponentCheckbox {
|
|||
const COLOR_UNCHECKED: WguiColor = WguiColor::Raw(drawing::Color::new(0., 0., 0., 0.));
|
||||
const COLOR_HOVERED: WguiColor = WguiColorName::Tertiary.to_wgui_color();
|
||||
|
||||
fn disabled_color() -> WguiColor {
|
||||
WguiColor::from(WguiColorName::OnBackground).with_alpha(0.35)
|
||||
}
|
||||
|
||||
/// Color for the inner checkbox box, for any checked/hover/disabled combination.
|
||||
fn box_fill_color(checked: bool, hovered: bool, disabled: bool, checked_color: WguiColor) -> WguiColor {
|
||||
if disabled {
|
||||
if checked { disabled_color() } else { COLOR_UNCHECKED }
|
||||
} else if checked {
|
||||
if hovered { COLOR_HOVERED } else { checked_color }
|
||||
} else {
|
||||
COLOR_UNCHECKED
|
||||
}
|
||||
}
|
||||
|
||||
/// Color for the checkbox border, for any hover/press/disabled combination.
|
||||
fn box_border_color(hovered: bool, down: bool, disabled: bool) -> WguiColor {
|
||||
if disabled {
|
||||
disabled_color()
|
||||
} else if hovered || down {
|
||||
COLOR_HOVERED
|
||||
} else {
|
||||
WguiColorName::OnBackground.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentTrait for ComponentCheckbox {
|
||||
fn base(&self) -> &ComponentBase {
|
||||
&self.base
|
||||
|
|
@ -120,17 +147,9 @@ impl ComponentTrait for ComponentCheckbox {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_box_checked(widgets: &layout::WidgetMap, data: &Data, checked: bool, hovered: bool) {
|
||||
fn set_box_checked(widgets: &layout::WidgetMap, data: &Data, checked: bool, hovered: bool, disabled: bool) {
|
||||
widgets.call(data.id_inner_box, |rect: &mut WidgetRectangle| {
|
||||
rect.params.color = if checked {
|
||||
if hovered {
|
||||
COLOR_HOVERED.into()
|
||||
} else {
|
||||
data.color_checked
|
||||
}
|
||||
} else {
|
||||
COLOR_UNCHECKED.into()
|
||||
}
|
||||
rect.params.color = box_fill_color(checked, hovered, disabled, data.color_checked);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -145,6 +164,7 @@ impl ComponentCheckbox {
|
|||
|
||||
pub fn set_checked(&self, common: &mut CallbackDataCommon, checked: bool) {
|
||||
let hovered;
|
||||
let disabled;
|
||||
{
|
||||
let mut state = self.state.borrow_mut();
|
||||
if state.checked == checked {
|
||||
|
|
@ -152,8 +172,9 @@ impl ComponentCheckbox {
|
|||
}
|
||||
state.checked = checked;
|
||||
hovered = state.hovered;
|
||||
disabled = state.disabled;
|
||||
}
|
||||
set_box_checked(&common.state.widgets, &self.data, checked, hovered);
|
||||
set_box_checked(&common.state.widgets, &self.data, checked, hovered, disabled);
|
||||
common.alterables.mark_redraw();
|
||||
}
|
||||
|
||||
|
|
@ -174,16 +195,46 @@ impl ComponentCheckbox {
|
|||
pub fn on_toggle(&self, func: CheckboxToggleCallback) {
|
||||
self.state.borrow_mut().on_toggle = Some(func);
|
||||
}
|
||||
|
||||
/// Enable or disable user interaction with the checkbox and dim its appearance.
|
||||
pub fn set_disabled(&self, common: &mut CallbackDataCommon, disabled: bool) {
|
||||
let checked;
|
||||
let hovered;
|
||||
let down;
|
||||
{
|
||||
let mut state = self.state.borrow_mut();
|
||||
if state.disabled == disabled {
|
||||
return;
|
||||
}
|
||||
state.disabled = disabled;
|
||||
checked = state.checked;
|
||||
hovered = state.hovered;
|
||||
down = state.down;
|
||||
}
|
||||
|
||||
set_box_checked(&common.state.widgets, &self.data, checked, hovered, disabled);
|
||||
|
||||
common.state.widgets.call(self.data.id_outer_box, |rect: &mut WidgetRectangle| {
|
||||
rect.params.border_color = box_border_color(hovered, down, disabled);
|
||||
});
|
||||
|
||||
if let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(self.data.id_label) {
|
||||
let color = if disabled { disabled_color() } else { WguiColorName::OnBackground.into() };
|
||||
label.set_color(common, color, true);
|
||||
}
|
||||
|
||||
common.alterables.mark_redraw();
|
||||
}
|
||||
|
||||
pub fn get_disabled(&self) -> bool {
|
||||
self.state.borrow().disabled
|
||||
}
|
||||
}
|
||||
|
||||
fn anim_hover(anim_data: &mut crate::animation::CallbackData<'_>, pos: f32, _pressed: bool) {
|
||||
fn anim_hover(anim_data: &mut crate::animation::CallbackData<'_>, pos: f32, pressed: bool, disabled: bool) {
|
||||
let rect = anim_data.obj.as_any_mut().downcast_mut::<WidgetRectangle>().unwrap();
|
||||
rect.params.border = 2.0;
|
||||
rect.params.border_color = if pos > 0.0 {
|
||||
COLOR_HOVERED.into()
|
||||
} else {
|
||||
WguiColorName::OnBackground.into()
|
||||
};
|
||||
rect.params.border_color = box_border_color(pos > 0.0, pressed, disabled);
|
||||
}
|
||||
|
||||
fn anim_hover_in(state: Rc<RefCell<State>>, data: Rc<Data>, anim_mult: f32) -> Animation {
|
||||
|
|
@ -193,7 +244,8 @@ fn anim_hover_in(state: Rc<RefCell<State>>, data: Rc<Data>, anim_mult: f32) -> A
|
|||
(5. * anim_mult) as _,
|
||||
AnimationEasing::OutQuad,
|
||||
Box::new(move |common, anim_data| {
|
||||
anim_hover(anim_data, anim_data.pos, down);
|
||||
let disabled = state.borrow().disabled;
|
||||
anim_hover(anim_data, anim_data.pos, down, disabled);
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
)
|
||||
|
|
@ -206,7 +258,8 @@ fn anim_hover_out(state: Rc<RefCell<State>>, data: Rc<Data>, anim_mult: f32) ->
|
|||
(8. * anim_mult) as _,
|
||||
AnimationEasing::OutQuad,
|
||||
Box::new(move |common, anim_data| {
|
||||
anim_hover(anim_data, 1.0 - anim_data.pos, down);
|
||||
let disabled = state.borrow().disabled;
|
||||
anim_hover(anim_data, 1.0 - anim_data.pos, down, disabled);
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
)
|
||||
|
|
@ -222,28 +275,33 @@ fn register_event_mouse_enter(
|
|||
listeners.register(
|
||||
EventListenerKind::MouseEnter,
|
||||
Box::new(move |common, _event_data, (), ()| {
|
||||
common.alterables.trigger_haptics();
|
||||
common
|
||||
.alterables
|
||||
.animate(anim_hover_in(state.clone(), data.clone(), anim_mult));
|
||||
let checked;
|
||||
let disabled;
|
||||
{
|
||||
let mut state = state.borrow_mut();
|
||||
checked = state.checked;
|
||||
disabled = state.disabled;
|
||||
state.hovered = true;
|
||||
}
|
||||
|
||||
if !disabled {
|
||||
common.alterables.trigger_haptics();
|
||||
common
|
||||
.alterables
|
||||
.animate(anim_hover_in(state.clone(), data.clone(), anim_mult));
|
||||
|
||||
if checked {
|
||||
common
|
||||
.state
|
||||
.widgets
|
||||
.call(data.id_inner_box, |rect: &mut WidgetRectangle| {
|
||||
rect.params.color = box_fill_color(checked, true, false, data.color_checked);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ComponentTooltip::register_hover_in(common, &tooltip_info, data.id_container, state.clone());
|
||||
|
||||
let checked = {
|
||||
let mut state = state.borrow_mut();
|
||||
state.hovered = true;
|
||||
state.checked
|
||||
};
|
||||
|
||||
if checked {
|
||||
common
|
||||
.state
|
||||
.widgets
|
||||
.call(data.id_inner_box, |rect: &mut WidgetRectangle| {
|
||||
rect.params.color = COLOR_HOVERED.into();
|
||||
});
|
||||
}
|
||||
|
||||
Ok(EventResult::Pass)
|
||||
}),
|
||||
)
|
||||
|
|
@ -258,25 +316,30 @@ fn register_event_mouse_leave(
|
|||
listeners.register(
|
||||
EventListenerKind::MouseLeave,
|
||||
Box::new(move |common, _event_data, (), ()| {
|
||||
common.alterables.trigger_haptics();
|
||||
common
|
||||
.alterables
|
||||
.animate(anim_hover_out(state.clone(), data.clone(), anim_mult));
|
||||
|
||||
let checked = {
|
||||
let checked;
|
||||
let disabled;
|
||||
{
|
||||
let mut state = state.borrow_mut();
|
||||
checked = state.checked;
|
||||
disabled = state.disabled;
|
||||
state.hovered = false;
|
||||
state.active_tooltip = None;
|
||||
state.checked
|
||||
};
|
||||
}
|
||||
|
||||
if checked {
|
||||
if !disabled {
|
||||
common.alterables.trigger_haptics();
|
||||
common
|
||||
.state
|
||||
.widgets
|
||||
.call(data.id_inner_box, |rect: &mut WidgetRectangle| {
|
||||
rect.params.color = data.color_checked;
|
||||
});
|
||||
.alterables
|
||||
.animate(anim_hover_out(state.clone(), data.clone(), anim_mult));
|
||||
|
||||
if checked {
|
||||
common
|
||||
.state
|
||||
.widgets
|
||||
.call(data.id_inner_box, |rect: &mut WidgetRectangle| {
|
||||
rect.params.color = box_fill_color(checked, false, false, data.color_checked);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(EventResult::Pass)
|
||||
|
|
@ -311,18 +374,14 @@ fn register_event_mouse_press(
|
|||
.widgets
|
||||
.call(data.id_outer_box, |rect: &mut WidgetRectangle| {
|
||||
rect.params.border = 2.0;
|
||||
rect.params.border_color = if pressed_hovered {
|
||||
COLOR_HOVERED.into()
|
||||
} else {
|
||||
WguiColorName::OnBackground.into()
|
||||
};
|
||||
rect.params.border_color = box_border_color(pressed_hovered, false, state.disabled);
|
||||
});
|
||||
|
||||
common.alterables.trigger_haptics();
|
||||
common.alterables.mark_redraw();
|
||||
common.alterables.unfocus();
|
||||
|
||||
if state.hovered {
|
||||
if state.hovered && !state.disabled {
|
||||
state.down = true;
|
||||
Ok(EventResult::Consumed)
|
||||
} else {
|
||||
|
|
@ -349,17 +408,13 @@ fn register_event_mouse_release(
|
|||
.widgets
|
||||
.call(data.id_outer_box, |rect: &mut WidgetRectangle| {
|
||||
rect.params.border = 2.0;
|
||||
rect.params.border_color = if released_hovered {
|
||||
COLOR_HOVERED.into()
|
||||
} else {
|
||||
WguiColorName::OnBackground.into()
|
||||
};
|
||||
rect.params.border_color = box_border_color(released_hovered, was_down, state.disabled);
|
||||
});
|
||||
|
||||
common.alterables.trigger_haptics();
|
||||
common.alterables.mark_redraw();
|
||||
|
||||
if was_down {
|
||||
if !state.disabled && was_down {
|
||||
state.down = false;
|
||||
|
||||
if let Some(self_ref) = state.self_ref.upgrade()
|
||||
|
|
@ -377,7 +432,7 @@ fn register_event_mouse_release(
|
|||
});
|
||||
}
|
||||
|
||||
set_box_checked(&common.state.widgets, &data, state.checked, state.hovered);
|
||||
set_box_checked(&common.state.widgets, &data, state.checked, state.hovered, state.disabled);
|
||||
if state.hovered
|
||||
&& let Some(on_toggle) = &state.on_toggle
|
||||
{
|
||||
|
|
@ -512,6 +567,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
|||
checked: params.checked,
|
||||
down: false,
|
||||
hovered: false,
|
||||
disabled: false,
|
||||
on_toggle: None,
|
||||
self_ref: Weak::new(),
|
||||
active_tooltip: None,
|
||||
|
|
|
|||
Loading…
Reference in New Issue