cosmic-settings/cosmic-settings/src/pages/input/mouse.rs
2026-05-15 16:26:20 -06:00

184 lines
7.1 KiB
Rust

// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic::iced::{Alignment, Length};
use cosmic::widget::{self, row, settings, text};
use cosmic::{Apply, Element};
use cosmic_comp_config::input::AccelProfile;
use cosmic_settings_page::{self as page, Section, section};
use slotmap::SlotMap;
use super::Message;
pub fn default_primary_button() -> cosmic::widget::segmented_button::SingleSelectModel {
let mut model = cosmic::widget::segmented_button::SingleSelectModel::builder()
.insert(|b| b.text(fl!("primary-button", "left")))
.insert(|b| b.text(fl!("primary-button", "right")))
.build();
model.activate_position(0);
model
}
#[derive(Default)]
pub struct Page {
entity: page::Entity,
}
impl page::Page<crate::pages::Message> for Page {
fn set_id(&mut self, entity: page::Entity) {
self.entity = entity;
}
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![sections.insert(mouse()), sections.insert(scrolling())])
}
fn info(&self) -> page::Info {
page::Info::new("mouse", "input-mouse-symbolic")
.title(fl!("mouse"))
.description(fl!("xdg-entry-mouse-comment"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}
fn mouse() -> Section<crate::pages::Message> {
crate::slab!(descriptions {
mouse_acceleration = fl!("mouse", "acceleration");
mouse_speed = fl!("mouse", "speed");
primary_button = fl!("primary-button");
acceleration_desc = fl!("acceleration-desc");
});
Section::default()
.descriptions(descriptions)
.view::<Page>(move |binder, _page, section| {
let descriptions = &section.descriptions;
let input = binder.page::<super::Page>().expect("input page not found");
settings::section()
.title(&section.title)
.add(
settings::flex_item(
&descriptions[primary_button],
cosmic::widget::segmented_control::horizontal(&input.primary_button)
.minimum_button_width(0)
.on_activate(|x| Message::PrimaryButtonSelected(x, false)),
)
.align_items(Alignment::Center),
)
.add(
settings::item::builder(&descriptions[mouse_speed]).flex_control({
let value = (input
.input_default
.acceleration
.as_ref()
.map_or(0.0, |x| x.speed)
+ 0.81)
* 70.71;
let slider = widget::slider(0.0..=100.0, value, |value| {
Message::SetMouseSpeed((value / 70.71) - 0.81, false)
})
.width(Length::Fill)
.breakpoints(&[50.0])
.apply(widget::container)
.max_width(250);
row::with_capacity(2)
.align_y(Alignment::Center)
.spacing(8)
.push(
text::body(format!("{:.0}", value.round()))
.width(Length::Fixed(22.0))
.align_x(Alignment::Center),
)
.push(slider)
}),
)
.add(
settings::item::builder(&descriptions[mouse_acceleration])
.description(&descriptions[acceleration_desc])
.toggler(
input
.input_default
.acceleration
.as_ref()
.is_none_or(|x| x.profile == Some(AccelProfile::Adaptive)),
|x| Message::SetAcceleration(x, false),
),
)
.apply(Element::from)
.map(crate::pages::Message::Input)
})
}
fn scrolling() -> Section<crate::pages::Message> {
crate::slab!(descriptions {
natural = fl!("scrolling", "natural");
natural_desc = fl!("scrolling", "natural-desc");
scroll_speed = fl!("scrolling", "speed");
});
Section::default()
.title(fl!("scrolling"))
.descriptions(descriptions)
.view::<Page>(move |binder, _page, section| {
let descriptions = &section.descriptions;
let input = binder.page::<super::Page>().expect("input page not found");
settings::section()
.title(&section.title)
.add(
settings::item::builder(&descriptions[scroll_speed])
.flex_control({
let value = input
.input_default
.scroll_config
.as_ref()
.and_then(|x| x.scroll_factor)
.unwrap_or(1.)
.log(2.)
* 10.0
+ 50.0;
let slider = widget::slider(1.0..=100.0, value, |value| {
Message::SetScrollFactor(2f64.powf((value - 50.0) / 10.0), false)
})
.width(Length::Fill)
.breakpoints(&[50.0])
.apply(widget::container)
.max_width(250);
row::with_capacity(2)
.align_y(Alignment::Center)
.spacing(8)
.push(
text::body(format!("{:.0}", value.round()))
.width(Length::Fixed(22.0))
.align_x(Alignment::Center),
)
.push(slider)
})
.align_items(Alignment::Center),
)
.add(
settings::item::builder(&descriptions[natural])
.description(&descriptions[natural_desc])
.toggler(
input
.input_default
.scroll_config
.as_ref()
.and_then(|x| x.natural_scroll)
.unwrap_or(false),
|x| Message::SetNaturalScroll(x, false),
),
)
.apply(Element::from)
.map(crate::pages::Message::Input)
})
}