refactor: use Slab for storing page section descriptions

This commit is contained in:
Michael Aaron Murphy 2024-06-06 15:52:21 +02:00
parent 17a74a512b
commit f6e50f1d9b
No known key found for this signature in database
GPG key ID: B2732D4240C9212C
24 changed files with 666 additions and 639 deletions

2
Cargo.lock generated
View file

@ -1366,6 +1366,7 @@ dependencies = [
"ron",
"rust-embed",
"serde",
"slab",
"slotmap",
"static_init",
"sunrise",
@ -1397,6 +1398,7 @@ dependencies = [
"libcosmic",
"once_cell",
"regex",
"slab",
"slotmap",
"tokio",
"url",

View file

@ -52,6 +52,7 @@ url = "2.5.0"
xkb-data = "0.1.0"
zbus = { version = "4.2.1", features = ["tokio"] }
tachyonix = "0.2.1"
slab = "0.4.9"
[dependencies.i18n-embed]
version = "0.14.1"

View file

@ -28,6 +28,7 @@ use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use cosmic_settings_wallpaper as wallpaper;
use ron::ser::PrettyConfig;
use slab::Slab;
use slotmap::SlotMap;
use tokio::io::AsyncBufReadExt;
@ -40,15 +41,15 @@ const ICON_PREV_ROW: usize = 3;
const ICON_TRY_SIZES: [u16; 3] = [32, 48, 64];
const ICON_THUMB_SIZE: u16 = 32;
const ICON_NAME_TRUNC: usize = 20;
type IconThemes = Vec<IconTheme>;
type IconHandles = Vec<[icon::Handle; ICON_PREV_N]>;
pub type IconThemes = Vec<IconTheme>;
pub type IconHandles = Vec<[icon::Handle; ICON_PREV_N]>;
crate::cache_dynamic_lazy! {
static HEX: String = fl!("hex");
static RGB: String = fl!("rgb");
static RESET_TO_DEFAULT: String = fl!("reset-to-default");
static ICON_THEME: String = fl!("icon-theme");
static ICON_THEME_DESC: String = fl!("icon-theme", "desc");
}
#[derive(Clone, Copy, Debug)]
@ -1134,34 +1135,26 @@ impl page::Page<crate::pages::Message> for Page {
#[allow(clippy::too_many_lines)]
pub fn mode_and_colors() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let auto_switch = descriptions.insert(fl!("auto-switch"));
let accent_color = descriptions.insert(fl!("accent-color"));
let app_bg = descriptions.insert(fl!("app-background"));
let container_bg = descriptions.insert(fl!("container-background"));
let container_bg_desc = descriptions.insert(fl!("container-background", "desc"));
let text_tint = descriptions.insert(fl!("text-tint"));
let text_tint_desc = descriptions.insert(fl!("text-tint", "desc"));
let control_tint = descriptions.insert(fl!("control-tint"));
let control_tint_desc = descriptions.insert(fl!("control-tint", "desc"));
let window_hint_toggle = descriptions.insert(fl!("window-hint-accent-toggle"));
let window_hint = descriptions.insert(fl!("window-hint-accent"));
let dark = descriptions.insert(fl!("dark"));
let light = descriptions.insert(fl!("light"));
Section::default()
.title(fl!("mode-and-colors"))
.descriptions(vec![
// 0
fl!("auto-switch").into(),
//1
fl!("accent-color").into(),
//2
fl!("app-background").into(),
//3
fl!("container-background").into(),
fl!("container-background", "desc").into(),
fl!("container-background", "desc-detail").into(),
fl!("container-background", "reset").into(),
// 7
fl!("text-tint").into(),
fl!("text-tint", "desc").into(),
// 9
fl!("control-tint").into(),
fl!("control-tint", "desc").into(),
// 11
fl!("window-hint-accent-toggle").into(),
fl!("window-hint-accent").into(),
// 13
fl!("dark").into(),
fl!("light").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
let palette = &page.theme_builder.palette.as_ref();
let cur_accent = page
@ -1182,7 +1175,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
.padding([8, 0])
.selected(page.theme_mode.is_dark)
.on_press(Message::DarkMode(true)),
text(&*descriptions[13])
text(&descriptions[dark])
]
.spacing(8)
.width(Length::FillPortion(1))
@ -1197,7 +1190,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
.selected(!page.theme_mode.is_dark)
.padding([8, 0])
.on_press(Message::DarkMode(false)),
text(&*descriptions[14])
text(&descriptions[light])
]
.spacing(8)
.width(Length::FillPortion(1))
@ -1211,7 +1204,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
.align_x(cosmic::iced_core::alignment::Horizontal::Center),
)
.add(
settings::item::builder(&*descriptions[0])
settings::item::builder(&descriptions[auto_switch])
.description(
if !page.day_time && page.theme_mode.is_dark {
&page.auto_switch_descs[0]
@ -1228,7 +1221,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
)
.add(
cosmic::iced::widget::column![
text(&*descriptions[1]),
text(&descriptions[accent_color]),
scrollable(
cosmic::iced::widget::row![
color_button(
@ -1324,7 +1317,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
.spacing(8),
)
.add(
settings::item::builder(&*descriptions[2]).control(
settings::item::builder(&descriptions[app_bg]).control(
page.application_background
.picker_button(Message::ApplicationBackground, Some(24))
.width(Length::Fixed(48.0))
@ -1332,8 +1325,8 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
),
)
.add(
settings::item::builder(&*descriptions[3])
.description(&*descriptions[4])
settings::item::builder(&descriptions[container_bg])
.description(&descriptions[container_bg_desc])
.control(if page.container_background.get_applied_color().is_some() {
Element::from(
page.container_background
@ -1353,8 +1346,8 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
}),
)
.add(
settings::item::builder(&*descriptions[7])
.description(&*descriptions[8])
settings::item::builder(&descriptions[text_tint])
.description(&descriptions[text_tint_desc])
.control(
page.interface_text
.picker_button(Message::InterfaceText, Some(24))
@ -1363,8 +1356,8 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
),
)
.add(
settings::item::builder(&*descriptions[9])
.description(&*descriptions[10])
settings::item::builder(&descriptions[control_tint])
.description(&descriptions[control_tint_desc])
.control(
page.control_component
.picker_button(Message::ControlComponent, Some(24))
@ -1373,12 +1366,12 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
),
)
.add(
settings::item::builder(&*descriptions[11])
settings::item::builder(&descriptions[window_hint_toggle])
.toggler(page.no_custom_window_hint, Message::UseDefaultWindowHint),
);
if !page.no_custom_window_hint {
section = section.add(
settings::item::builder(&*descriptions[12]).control(
settings::item::builder(&descriptions[window_hint]).control(
page.accent_window_hint
.picker_button(Message::AccentWindowHint, Some(24))
.width(Length::Fixed(48.0))
@ -1394,14 +1387,16 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
#[allow(clippy::too_many_lines)]
pub fn style() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let round = descriptions.insert(fl!("style", "round"));
let slightly_round = descriptions.insert(fl!("style", "slightly-round"));
let square = descriptions.insert(fl!("style", "square"));
Section::default()
.title(fl!("style"))
.descriptions(vec![
fl!("style", "round").into(),
fl!("style", "slightly-round").into(),
fl!("style", "square").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
@ -1425,7 +1420,7 @@ pub fn style() -> Section<crate::pages::Message> {
.style(button::Style::Image)
.padding(8)
.on_press(Message::Roundness(Roundness::Round)),
text(&*descriptions[0])
text(&descriptions[round])
]
.spacing(8)
.width(Length::FillPortion(1))
@ -1447,7 +1442,7 @@ pub fn style() -> Section<crate::pages::Message> {
.style(button::Style::Image)
.padding(8)
.on_press(Message::Roundness(Roundness::SlightlyRound)),
text(&*descriptions[1])
text(&descriptions[slightly_round])
]
.spacing(8)
.width(Length::FillPortion(1))
@ -1470,7 +1465,7 @@ pub fn style() -> Section<crate::pages::Message> {
.style(button::Style::Image)
.padding(8)
.on_press(Message::Roundness(Roundness::Square)),
text(&*descriptions[2])
text(&descriptions[square])
]
.spacing(8)
.align_items(cosmic::iced_core::Alignment::Center)
@ -1490,23 +1485,25 @@ pub fn style() -> Section<crate::pages::Message> {
#[allow(clippy::too_many_lines)]
pub fn window_management() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let active_hint = descriptions.insert(fl!("window-management", "active-hint"));
let gaps = descriptions.insert(fl!("window-management", "gaps"));
Section::default()
.title(fl!("window-management"))
.descriptions(vec![
fl!("window-management", "active-hint").into(),
fl!("window-management", "gaps").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item::builder(&*descriptions[0]).control(
.add(settings::item::builder(&descriptions[active_hint]).control(
cosmic::widget::spin_button(
page.theme_builder.active_hint.to_string(),
Message::WindowHintSize,
),
))
.add(settings::item::builder(&*descriptions[1]).control(
.add(settings::item::builder(&descriptions[gaps]).control(
cosmic::widget::spin_button(
page.theme_builder.gaps.1.to_string(),
Message::GapSize,
@ -1518,10 +1515,14 @@ pub fn window_management() -> Section<crate::pages::Message> {
}
pub fn experimental() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let experimental_label = descriptions.insert(fl!("experimental-settings"));
Section::default()
.descriptions(vec![fl!("experimental-settings").into()])
.view::<Page>(|_binder, _page, section| {
let descriptions = &*section.descriptions;
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
let descriptions = &section.descriptions;
let control = row::with_children(vec![
horizontal_space(Length::Fill).into(),
@ -1530,7 +1531,7 @@ pub fn experimental() -> Section<crate::pages::Message> {
settings::view_section("")
.add(
settings::item::builder(&*descriptions[0])
settings::item::builder(&descriptions[experimental_label])
.control(control)
.apply(container)
.style(cosmic::theme::Container::List)
@ -1545,12 +1546,16 @@ pub fn experimental() -> Section<crate::pages::Message> {
#[allow(clippy::too_many_lines)]
pub fn reset_button() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let reset_to_default = descriptions.insert(fl!("reset-to-default"));
Section::default()
.descriptions(vec![fl!("reset-to-default").into()])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
if page.can_reset {
button::standard(&*descriptions[0])
button::standard(&descriptions[reset_to_default])
.on_press(Message::Reset)
.into()
} else {

View file

@ -2,7 +2,7 @@ use cosmic::{
cosmic_config::CosmicConfigEntry,
iced::{alignment, Length},
iced_runtime::Command,
widget::{button, container, row, text},
widget::{button, container, row},
Apply, Element,
};
use cosmic_panel_config::CosmicPanelConfig;

View file

@ -8,6 +8,7 @@ use cosmic::{
};
use cosmic_panel_config::{CosmicPanelConfig, CosmicPanelContainerConfig};
use cosmic_settings_page::{self as page, section, Section};
use slab::Slab;
use slotmap::SlotMap;
use tracing::error;
@ -142,16 +143,20 @@ impl Default for Page {
}
pub(crate) fn enable() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let dock = descriptions.insert(fl!("dock"));
Section::default()
.descriptions(vec![fl!("dock").into()])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
let Some(container_config) = page.inner.container_config.as_ref() else {
return Element::from(text(fl!("unknown")));
};
settings::view_section(&section.title)
.add(settings::flex_item(
&*descriptions[0],
&descriptions[dock],
toggler(
None,
container_config

View file

@ -11,6 +11,7 @@ use cosmic::{
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slab::Slab;
use slotmap::SlotMap;
#[derive(Default)]
@ -44,27 +45,29 @@ impl page::AutoBind<crate::pages::Message> for Page {
}
pub fn super_key_action() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let launcher = descriptions.insert(fl!("super-key-action", "launcher"));
let workspaces = descriptions.insert(fl!("super-key-action", "workspaces"));
let applications = descriptions.insert(fl!("super-key-action", "applications"));
Section::default()
.title(fl!("super-key-action"))
.descriptions(vec![
fl!("super-key-action", "launcher").into(),
fl!("super-key-action", "workspaces").into(),
fl!("super-key-action", "applications").into(),
])
.view::<Page>(|_binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item(
&*descriptions[0],
&descriptions[launcher],
horizontal_space(Length::Fill),
))
.add(settings::item(
&*descriptions[1],
&descriptions[workspaces],
horizontal_space(Length::Fill),
))
.add(settings::item(
&*descriptions[2],
&descriptions[applications],
horizontal_space(Length::Fill),
))
.into()
@ -72,13 +75,15 @@ pub fn super_key_action() -> Section<crate::pages::Message> {
}
pub fn window_controls() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let minimize = descriptions.insert(fl!("window-controls", "minimize"));
let maximize = descriptions.insert(fl!("window-controls", "maximize"));
Section::default()
.title(fl!("window-controls"))
.descriptions(vec![
fl!("window-controls", "minimize").into(),
fl!("window-controls", "maximize").into(),
])
.view::<Page>(|binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |binder, _page, section| {
let desktop = binder
.page::<super::Page>()
.expect("desktop page not found");
@ -86,7 +91,7 @@ pub fn window_controls() -> Section<crate::pages::Message> {
settings::view_section(&section.title)
.add(settings::flex_item(
&*descriptions[0],
&descriptions[minimize],
toggler(
None,
desktop.cosmic_tk.show_minimize,
@ -94,7 +99,7 @@ pub fn window_controls() -> Section<crate::pages::Message> {
),
))
.add(settings::flex_item(
&*descriptions[1],
&descriptions[maximize],
toggler(
None,
desktop.cosmic_tk.show_maximize,
@ -109,7 +114,7 @@ pub fn window_controls() -> Section<crate::pages::Message> {
pub fn panel_dock_links() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("desktop-panels-and-applets"))
.view::<Page>(|binder, _page, section| {
.view::<Page>(move |binder, _page, section| {
// TODO probably a way of getting the entity and its info
let mut settings = settings::view_section(&section.title);
settings = if let Some((panel_entity, panel_info)) =

View file

@ -15,6 +15,7 @@ use cosmic_panel_config::{
CosmicPanelOuput, PanelAnchor, PanelSize,
};
use cosmic_settings_page::{self as page, Section};
use slab::Slab;
use std::collections::HashMap;
pub struct PageInner {
@ -93,13 +94,15 @@ pub(crate) fn behavior_and_position<
p: &P,
msg_map: T,
) -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let autohide_label = descriptions.insert(p.autohide_label());
let position = descriptions.insert(fl!("panel-behavior-and-position", "position"));
let display = descriptions.insert(fl!("panel-behavior-and-position", "display"));
Section::default()
.title(fl!("panel-behavior-and-position"))
.descriptions(vec![
p.autohide_label().into(),
fl!("panel-behavior-and-position", "position").into(),
fl!("panel-behavior-and-position", "display").into(),
])
.descriptions(descriptions)
.view::<P>(move |_binder, page, section| {
let descriptions = &section.descriptions;
let page = page.inner();
@ -108,13 +111,13 @@ pub(crate) fn behavior_and_position<
};
settings::view_section(&section.title)
.add(settings::flex_item(
&*descriptions[0],
&descriptions[autohide_label],
toggler(None, panel_config.autohide.is_some(), |value| {
Message::AutoHidePanel(value)
}),
))
.add(settings::flex_item(
&*descriptions[1],
&descriptions[position],
dropdown(
page.anchors.as_slice(),
Some(panel_config.anchor as usize),
@ -122,7 +125,7 @@ pub(crate) fn behavior_and_position<
),
))
.add(settings::flex_item(
&*descriptions[2],
&descriptions[display],
dropdown(
page.outputs.as_slice(),
match &panel_config.output {
@ -145,15 +148,17 @@ pub(crate) fn style<
p: &P,
msg_map: T,
) -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let gap_label = descriptions.insert(p.gap_label());
let extend_label = descriptions.insert(p.extend_label());
let appearance = descriptions.insert(fl!("panel-style", "appearance"));
let background_opacity = descriptions.insert(fl!("panel-style", "background-opacity"));
let size = descriptions.insert(fl!("panel-style", "size"));
Section::default()
.title(fl!("panel-style"))
.descriptions(vec![
p.gap_label().into(),
p.extend_label().into(),
fl!("panel-style", "appearance").into(),
fl!("panel-style", "size").into(),
fl!("panel-style", "background-opacity").into(),
])
.descriptions(descriptions)
.view::<P>(move |_binder, page, section| {
let descriptions = &section.descriptions;
let inner = page.inner();
@ -162,19 +167,19 @@ pub(crate) fn style<
};
settings::view_section(&section.title)
.add(settings::flex_item(
&*descriptions[0],
&descriptions[gap_label],
toggler(None, panel_config.anchor_gap, |value| {
Message::AnchorGap(value)
}),
))
.add(settings::flex_item(
&*descriptions[1],
&descriptions[extend_label],
toggler(None, panel_config.expand_to_edges, |value| {
Message::ExtendToEdge(value)
}),
))
.add(settings::flex_item(
&*descriptions[2],
&descriptions[appearance],
dropdown(
inner.backgrounds.as_slice(),
match panel_config.background {
@ -187,7 +192,7 @@ pub(crate) fn style<
),
))
.add(settings::flex_item(
&*descriptions[3],
&descriptions[size],
// TODO custom discrete slider variant
row::with_children(vec![
text(fl!("small")).into(),
@ -220,7 +225,7 @@ pub(crate) fn style<
.spacing(12),
))
.add(settings::flex_item(
&*descriptions[4],
&descriptions[background_opacity],
row::with_children(vec![
text(fl!("number", HashMap::from_iter(vec![("number", 0)]))).into(),
slider(0..=100, (panel_config.opacity * 100.0) as i32, |v| {
@ -240,9 +245,13 @@ pub(crate) fn style<
pub(crate) fn configuration<P: page::Page<crate::pages::Message> + PanelPage>(
p: &P,
) -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let applets_label = descriptions.insert(p.configure_applets_label());
Section::default()
.title(fl!("panel-applets"))
.descriptions(vec![p.configure_applets_label().into()])
.descriptions(descriptions)
.view::<P>(move |binder, page, section| {
let mut settings = settings::view_section(&section.title);
let descriptions = &section.descriptions;
@ -257,7 +266,7 @@ pub(crate) fn configuration<P: page::Page<crate::pages::Message> + PanelPage>(
]);
settings.add(
settings::item::builder(&*descriptions[0])
settings::item::builder(&*descriptions[applets_label])
.control(control)
.spacing(16)
.apply(container)
@ -281,12 +290,16 @@ pub(crate) fn add_panel<
>(
msg_map: T,
) -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let reset_to_default = descriptions.insert(fl!("reset-to-default"));
Section::default()
.title(fl!("panel-missing"))
.descriptions(vec![fl!("reset-to-default").into()])
.descriptions(descriptions)
.view::<P>(move |_binder, _page, section| {
let descriptions = &section.descriptions;
button::standard(&*descriptions[0])
button::standard(&descriptions[reset_to_default])
.on_press(Message::FullReset)
.apply(Element::from)
.map(msg_map)
@ -300,15 +313,19 @@ pub fn reset_button<
>(
msg_map: T,
) -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let reset_to_default = descriptions.insert(fl!("reset-to-default"));
Section::default()
.descriptions(vec![fl!("reset-to-default").into()])
.descriptions(descriptions)
.view::<P>(move |_binder, page, section| {
let descriptions = &section.descriptions;
let inner = page.inner();
if inner.system_default == inner.panel_config {
Element::from(horizontal_space(1))
} else {
button::standard(&*descriptions[0])
button::standard(&descriptions[reset_to_default])
.on_press(Message::ResetPanel)
.into()
}

View file

@ -14,7 +14,7 @@ use std::{
sync::Arc,
};
use cosmic::{app, command, Apply, Command};
use cosmic::{command, Apply, Command};
use cosmic::{
dialog::file_chooser,
widget::{
@ -46,6 +46,7 @@ use cosmic_settings_page::{self as page, section};
use cosmic_settings_wallpaper::{self as wallpaper, Entry, ScalingMode};
use image::imageops::FilterType::Lanczos3;
use image::{ImageBuffer, Rgba};
use slab::Slab;
use slotmap::{DefaultKey, SecondaryMap, SlotMap};
const ZOOM: usize = 0;
@ -1145,23 +1146,19 @@ pub async fn change_folder(current_folder: PathBuf, recurse: bool) -> Context {
update
}
crate::cache_dynamic_lazy! {
static WALLPAPER_SAME: String = fl!("wallpaper", "same");
static WALLPAPER_FIT: String = fl!("wallpaper", "fit");
static WALLPAPER_SLIDE: String = fl!("wallpaper", "slide");
static WALLPAPER_CHANGE: String = fl!("wallpaper", "change");
}
#[allow(clippy::too_many_lines)]
pub fn settings() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let same_label = descriptions.insert(fl!("wallpaper", "same"));
let fit_label = descriptions.insert(fl!("wallpaper", "fit"));
let slide_label = descriptions.insert(fl!("wallpaper", "slide"));
let change_label = descriptions.insert(fl!("wallpaper", "change"));
Section::default()
.descriptions(vec![
WALLPAPER_SAME.as_str().into(),
WALLPAPER_FIT.as_str().into(),
WALLPAPER_SLIDE.as_str().into(),
WALLPAPER_CHANGE.as_str().into(),
])
.view::<Page>(|_binder, page, _section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
let mut children = Vec::with_capacity(3);
let mut show_slideshow_toggle = true;
@ -1227,18 +1224,18 @@ pub fn settings() -> Section<crate::pages::Message> {
children.push({
let mut column = list_column()
.add(settings::flex_item(
&*WALLPAPER_SAME,
&descriptions[same_label],
toggler(
None,
page.wallpaper_service_config.same_on_all,
Message::SameWallpaper,
),
))
.add(settings::flex_item(&*WALLPAPER_FIT, wallpaper_fit));
.add(settings::flex_item(&descriptions[fit_label], wallpaper_fit));
if show_slideshow_toggle {
column = column.add(settings::flex_item(
&*WALLPAPER_SLIDE,
&descriptions[slide_label],
toggler(None, slideshow_enabled, Message::Slideshow),
));
}
@ -1247,7 +1244,7 @@ pub fn settings() -> Section<crate::pages::Message> {
if slideshow_enabled {
column
.add(settings::flex_item(
&*WALLPAPER_CHANGE,
&descriptions[change_label],
dropdown(
&page.rotation_options,
Some(page.selected_rotation),

View file

@ -12,6 +12,7 @@ use cosmic::{
use cosmic_comp_config::workspace::{WorkspaceConfig, WorkspaceLayout, WorkspaceMode};
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slab::Slab;
use slotmap::SlotMap;
use tracing::error;
@ -114,24 +115,26 @@ impl Page {
}
fn multi_behavior() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let span = descriptions.insert(fl!("workspaces-multi-behavior", "span"));
let separate = descriptions.insert(fl!("workspaces-multi-behavior", "separate"));
Section::default()
.title(fl!("workspaces-multi-behavior"))
.descriptions(vec![
fl!("workspaces-multi-behavior", "span").into(),
fl!("workspaces-multi-behavior", "separate").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item_row(vec![radio(
&*descriptions[0],
&descriptions[span],
WorkspaceMode::Global,
Some(page.comp_workspace_config.workspace_mode),
Message::SetWorkspaceMode,
)
.into()]))
.add(settings::item_row(vec![radio(
&*descriptions[1],
&descriptions[separate],
WorkspaceMode::OutputBound,
Some(page.comp_workspace_config.workspace_mode),
Message::SetWorkspaceMode,
@ -143,24 +146,26 @@ fn multi_behavior() -> Section<crate::pages::Message> {
}
fn workspace_orientation() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let vertical = descriptions.insert(fl!("workspaces-orientation", "vertical"));
let horizontal = descriptions.insert(fl!("workspaces-orientation", "horizontal"));
Section::default()
.title(fl!("workspaces-orientation"))
.descriptions(vec![
fl!("workspaces-orientation", "vertical").into(),
fl!("workspaces-orientation", "horizontal").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item_row(vec![radio(
&*descriptions[0],
&*descriptions[vertical],
WorkspaceLayout::Vertical,
Some(page.comp_workspace_config.workspace_layout),
Message::SetWorkspaceLayout,
)
.into()]))
.add(settings::item_row(vec![radio(
&*descriptions[1],
&*descriptions[horizontal],
WorkspaceLayout::Horizontal,
Some(page.comp_workspace_config.workspace_layout),
Message::SetWorkspaceLayout,

View file

@ -3,7 +3,6 @@
pub mod arrangement;
// pub mod night_light;
pub mod text;
use crate::{app, pages};
use arrangement::Arrangement;
@ -16,6 +15,7 @@ use cosmic::widget::{
use cosmic::{command, Apply, Command, Element};
use cosmic_randr_shell::{List, Output, OutputKey, Transform};
use cosmic_settings_page::{self as page, section, Section};
use slab::Slab;
use slotmap::{Key, SlotMap};
use std::collections::BTreeMap;
use std::{process::ExitStatus, sync::Arc};
@ -145,7 +145,7 @@ struct Config {
#[derive(Default)]
struct ViewCache {
modes: BTreeMap<(u32, u32), Vec<u32>>,
orientations: [&'static str; 4],
orientations: [String; 4],
refresh_rates: Vec<String>,
resolutions: Vec<String>,
orientation_selected: Option<usize>,
@ -170,33 +170,12 @@ impl page::Page<crate::pages::Message> for Page {
// text::NIGHT_LIGHT_AUTO.as_str().into(),
// text::NIGHT_LIGHT_DESCRIPTION.as_str().into(),
// ])
// .view::<Page>(|_binder, page, _section| page.night_light_view()),
// .view::<Page>(move |_binder, page, _section| page.night_light_view()),
// ),
// Display arrangement
sections.insert(
Section::default()
.title(&*text::DISPLAY_ARRANGEMENT)
.descriptions(vec![
text::DISPLAY_ARRANGEMENT.as_str().into(),
text::DISPLAY_ARRANGEMENT_DESC.as_str().into(),
])
// Show section when there is more than 1 display
.show_while::<Page>(|page| page.list.outputs.len() > 1)
.view::<Page>(|_binder, page, _section| page.display_arrangement_view()),
),
sections.insert(display_arrangement()),
// Display configuration
sections.insert(
Section::default()
.descriptions([
text::DISPLAY.as_str().into(),
text::DISPLAY_REFRESH_RATE.as_str().into(),
text::DISPLAY_SCALE.as_str().into(),
text::ORIENTATION.as_str().into(),
text::ORIENTATION_STANDARD.as_str().into(),
text::ORIENTATION_ROTATE_90.as_str().into(),
])
.view::<Page>(|_binder, page, _section| page.display_view()),
),
sections.insert(display_configuration()),
])
}
@ -368,10 +347,10 @@ impl Page {
}
self.cache.orientations = [
text::ORIENTATION_STANDARD.as_str(),
text::ORIENTATION_ROTATE_90.as_str(),
text::ORIENTATION_ROTATE_180.as_str(),
text::ORIENTATION_ROTATE_270.as_str(),
fl!("orientation", "standard"),
fl!("orientation", "rotate-90"),
fl!("orientation", "rotate-180"),
fl!("orientation", "rotate-270"),
];
}
}
@ -382,119 +361,6 @@ impl Page {
)
}
/// View for the display arrangement section.
pub fn display_arrangement_view(&self) -> Element<pages::Message> {
let theme = cosmic::theme::active();
column()
.padding(cosmic::iced::Padding::from([
theme.cosmic().space_s(),
theme.cosmic().space_m(),
]))
.spacing(theme.cosmic().space_xs())
.push(cosmic::widget::text::body(&*text::DISPLAY_ARRANGEMENT_DESC))
.push({
Arrangement::new(&self.list, &self.display_tabs)
.on_select(|id| pages::Message::Displays(Message::Display(id)))
.on_placement(|id, x, y| pages::Message::Displays(Message::Position(id, x, y)))
.apply(cosmic::widget::scrollable)
.id(self.display_arrangement_scrollable.clone())
.width(Length::Shrink)
.direction(Direction::Horizontal(Properties::new()))
.apply(container)
.center_x()
.width(Length::Fill)
})
.apply(cosmic::widget::list::container)
.into()
}
/// View for the display configuration section.
pub fn display_view(&self) -> Element<pages::Message> {
let theme = cosmic::theme::active();
let Some(&active_id) = self.display_tabs.active_data::<OutputKey>() else {
return column().into();
};
let active_output = &self.list.outputs[active_id];
let display_options = active_output.enabled.then(|| {
list_column()
.add(cosmic::widget::settings::flex_item(
&*text::DISPLAY_RESOLUTION,
dropdown(
&self.cache.resolutions,
self.cache.resolution_selected,
Message::Resolution,
),
))
.add(cosmic::widget::settings::flex_item(
&*text::DISPLAY_REFRESH_RATE,
dropdown(
&self.cache.refresh_rates,
self.cache.refresh_rate_selected,
Message::RefreshRate,
),
))
.add(cosmic::widget::settings::flex_item(
&*text::DISPLAY_SCALE,
dropdown(
&["50%", "75%", "100%", "125%", "150%", "175%", "200%"],
self.cache.scale_selected,
Message::Scale,
),
))
.add(cosmic::widget::settings::flex_item(
&*text::ORIENTATION,
dropdown(
&self.cache.orientations,
self.cache.orientation_selected,
|id| {
Message::Orientation(match id {
0 => Transform::Normal,
1 => Transform::Rotate90,
2 => Transform::Rotate180,
_ => Transform::Rotate270,
})
},
),
))
});
let mut content = column().spacing(theme.cosmic().space_m());
if self.list.outputs.len() > 1 {
let display_switcher = tab_bar::horizontal(&self.display_tabs)
.button_alignment(Alignment::Center)
.on_activate(Message::Display);
let display_enable = (self
// Don't allow disabling display if it's the only active
.list
.outputs
.values()
.filter(|display| display.enabled)
.count()
> 1
|| !active_output.enabled)
.then(|| {
list_column().add(cosmic::widget::settings::flex_item(
&*text::DISPLAY_ENABLE,
toggler(None, active_output.enabled, Message::DisplayToggle),
))
});
content = content.push(display_switcher).push_maybe(display_enable);
}
content
.push(cosmic::widget::text::heading(&*text::DISPLAY_OPTIONS))
.push_maybe(display_options)
.apply(Element::from)
.map(pages::Message::Displays)
}
/// Displays the night light context drawer.
// pub fn night_light_context_view(&self) -> Element<pages::Message> {
// column().into()
@ -519,7 +385,7 @@ impl Page {
.map(|(key, output)| (&*output.name, key))
.collect::<BTreeMap<_, _>>();
for (pos, (name, id)) in sorted_outputs.into_iter().enumerate() {
for (pos, (_name, id)) in sorted_outputs.into_iter().enumerate() {
let Some(output) = self.list.outputs.get(id) else {
continue;
};
@ -824,6 +690,151 @@ impl Page {
}
}
/// View for the display arrangement section.
pub fn display_arrangement() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
_ = descriptions.insert(fl!("display", "arrangement"));
let display_arrangement_desc = descriptions.insert(fl!("display", "arrangement-desc"));
Section::default()
.title(fl!("display", "arrangement"))
.descriptions(descriptions)
// Show section when there is more than 1 display
.show_while::<Page>(|page| page.list.outputs.len() > 1)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
let theme = cosmic::theme::active();
column()
.padding(cosmic::iced::Padding::from([
theme.cosmic().space_s(),
theme.cosmic().space_m(),
]))
.spacing(theme.cosmic().space_xs())
.push(cosmic::widget::text::body(
&descriptions[display_arrangement_desc],
))
.push({
Arrangement::new(&page.list, &page.display_tabs)
.on_select(|id| pages::Message::Displays(Message::Display(id)))
.on_placement(|id, x, y| {
pages::Message::Displays(Message::Position(id, x, y))
})
.apply(cosmic::widget::scrollable)
.id(page.display_arrangement_scrollable.clone())
.width(Length::Shrink)
.direction(Direction::Horizontal(Properties::new()))
.apply(container)
.center_x()
.width(Length::Fill)
})
.apply(cosmic::widget::list::container)
.into()
})
}
/// View for the display configuration section.
pub fn display_configuration() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let _display = descriptions.insert(fl!("display"));
let refresh_rate = descriptions.insert(fl!("display", "refresh-rate"));
let resolution = descriptions.insert(fl!("display", "resolution"));
let scale = descriptions.insert(fl!("display", "scale"));
let orientation = descriptions.insert(fl!("orientation"));
let enable_label = descriptions.insert(fl!("display", "enable"));
let options_label = descriptions.insert(fl!("display", "options"));
Section::default()
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
let theme = cosmic::theme::active();
let Some(&active_id) = page.display_tabs.active_data::<OutputKey>() else {
return column().into();
};
let active_output = &page.list.outputs[active_id];
let display_options = active_output.enabled.then(|| {
list_column()
.add(cosmic::widget::settings::flex_item(
&descriptions[resolution],
dropdown(
&page.cache.resolutions,
page.cache.resolution_selected,
Message::Resolution,
),
))
.add(cosmic::widget::settings::flex_item(
&descriptions[refresh_rate],
dropdown(
&page.cache.refresh_rates,
page.cache.refresh_rate_selected,
Message::RefreshRate,
),
))
.add(cosmic::widget::settings::flex_item(
&descriptions[scale],
dropdown(
&["50%", "75%", "100%", "125%", "150%", "175%", "200%"],
page.cache.scale_selected,
Message::Scale,
),
))
.add(cosmic::widget::settings::flex_item(
&descriptions[orientation],
dropdown(
&page.cache.orientations,
page.cache.orientation_selected,
|id| {
Message::Orientation(match id {
0 => Transform::Normal,
1 => Transform::Rotate90,
2 => Transform::Rotate180,
_ => Transform::Rotate270,
})
},
),
))
});
let mut content = column().spacing(theme.cosmic().space_m());
if page.list.outputs.len() > 1 {
let display_switcher = tab_bar::horizontal(&page.display_tabs)
.button_alignment(Alignment::Center)
.on_activate(Message::Display);
let display_enable = (page
// Don't allow disabling display if it's the only active
.list
.outputs
.values()
.filter(|display| display.enabled)
.count()
> 1
|| !active_output.enabled)
.then(|| {
list_column().add(cosmic::widget::settings::flex_item(
&descriptions[enable_label],
toggler(None, active_output.enabled, Message::DisplayToggle),
))
});
content = content.push(display_switcher).push_maybe(display_enable);
}
content
.push(cosmic::widget::text::heading(&descriptions[options_label]))
.push_maybe(display_options)
.apply(Element::from)
.map(pages::Message::Displays)
})
}
fn cache_rates(cached_rates: &mut Vec<String>, rates: &[u32]) {
*cached_rates = rates
.iter()

View file

@ -1,36 +0,0 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
crate::cache_dynamic_lazy! {
pub static COLOR: String = fl!("color");
pub static COLOR_DEPTH: String = fl!("color", "depth");
pub static COLOR_PROFILE: String = fl!("color", "profile");
pub static COLOR_PROFILES: String = fl!("color", "sidebar");
pub static COLOR_TEMPERATURE: String = fl!("color", "temperature");
pub static DISPLAY: String = fl!("display");
pub static DISPLAY_ARRANGEMENT: String = fl!("display", "arrangement");
pub static DISPLAY_ARRANGEMENT_DESC: String = fl!("display", "arrangement-desc");
pub static DISPLAY_ENABLE: String = fl!("display", "enable");
pub static DISPLAY_EXTERNAL: String = fl!("display", "external");
pub static DISPLAY_LAPTOP: String = fl!("display", "laptop");
pub static DISPLAY_OPTIONS: String = fl!("display", "options");
pub static DISPLAY_REFRESH_RATE: String = fl!("display", "refresh-rate");
pub static DISPLAY_RESOLUTION: String = fl!("display", "resolution");
pub static DISPLAY_SCALE: String = fl!("display", "scale");
pub static MIRRORING: String = fl!("mirroring");
pub static NIGHT_LIGHT: String = fl!("night-light");
pub static NIGHT_LIGHT_AUTO: String = fl!("night-light", "auto");
pub static NIGHT_LIGHT_DESCRIPTION: String = fl!("night-light", "desc");
pub static ORIENTATION: String = fl!("orientation");
pub static ORIENTATION_STANDARD: String = fl!("orientation", "standard");
pub static ORIENTATION_ROTATE_90: String = fl!("orientation", "rotate-90");
pub static ORIENTATION_ROTATE_180: String = fl!("orientation", "rotate-180");
pub static ORIENTATION_ROTATE_270: String = fl!("orientation", "rotate-270");
pub static SCHEDULING: String = fl!("scheduling");
pub static SCHEDULING_MANUAL: String = fl!("scheduling", "manual");
}

View file

@ -11,6 +11,7 @@ use cosmic::{
use cosmic_comp_config::XkbConfig;
use cosmic_settings_page::{self as page, section, Section};
use itertools::Itertools;
use slab::Slab;
use slotmap::{DefaultKey, SlotMap};
static COMPOSE_OPTIONS: &[(&str, &str)] = &[
@ -568,7 +569,7 @@ impl page::AutoBind<crate::pages::Message> for Page {
fn input_sources() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("keyboard-sources"))
.view::<Page>(|_binder, page, section| {
.view::<Page>(move |_binder, page, section| {
// TODO Need something more custom, with drag and drop
let mut section = settings::view_section(&section.title);
@ -596,22 +597,24 @@ fn input_sources() -> Section<crate::pages::Message> {
}
fn special_character_entry() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let alternate = descriptions.insert(fl!("keyboard-special-char", "alternate"));
let compose = descriptions.insert(fl!("keyboard-special-char", "compose"));
Section::default()
.title(fl!("keyboard-special-char"))
.descriptions(vec![
fl!("keyboard-special-char", "alternate").into(),
fl!("keyboard-special-char", "compose").into(),
])
.view::<Page>(|_binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(go_next_item(
&*descriptions[0],
&*descriptions[alternate],
Message::OpenSpecialCharacterContext(SpecialKey::AlternateCharacters),
))
.add(go_next_item(
&*descriptions[1],
&*descriptions[compose],
Message::OpenSpecialCharacterContext(SpecialKey::Compose),
))
.apply(cosmic::Element::from)
@ -620,10 +623,14 @@ fn special_character_entry() -> Section<crate::pages::Message> {
}
fn keyboard_shortcuts() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let shortcuts_desc = descriptions.insert(fl!("keyboard-shortcuts", "desc"));
Section::default()
.title(fl!("keyboard-shortcuts"))
.descriptions(vec![fl!("keyboard-shortcuts", "desc").into()])
.view::<Page>(|binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |binder, _page, section| {
let descriptions = &section.descriptions;
let mut section = settings::view_section(&section.title);
@ -633,7 +640,7 @@ fn keyboard_shortcuts() -> Section<crate::pages::Message> {
.find(|(_, v)| v.id == "keyboard-shortcuts")
{
section = section.add(go_next_item(
&*descriptions[0],
&descriptions[shortcuts_desc],
crate::pages::Message::Page(shortcuts_entity),
));
}
@ -642,22 +649,24 @@ fn keyboard_shortcuts() -> Section<crate::pages::Message> {
}
fn keyboard_typing_assist() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let repeat_delay = descriptions.insert(fl!("keyboard-typing-assist", "repeat-delay"));
let repeat_rate = descriptions.insert(fl!("keyboard-typing-assist", "repeat-rate"));
let short = descriptions.insert(fl!("short"));
let long = descriptions.insert(fl!("long"));
let slow = descriptions.insert(fl!("slow"));
let fast = descriptions.insert(fl!("fast"));
Section::default()
.title(fl!("keyboard-typing-assist"))
.descriptions(vec![
fl!("keyboard-typing-assist", "repeat-delay").into(),
fl!("keyboard-typing-assist", "repeat-rate").into(),
fl!("short").into(),
fl!("long").into(),
fl!("slow").into(),
fl!("fast").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
let theme = cosmic::theme::active();
settings::view_section(&section.title)
.add(settings::flex_item(&*descriptions[0], {
.add(settings::flex_item(&descriptions[repeat_delay], {
// Delay
let delay_slider = cosmic::widget::slider(
KB_REPEAT_DELAY_MIN..=KB_REPEAT_DELAY_MAX,
@ -671,11 +680,11 @@ fn keyboard_typing_assist() -> Section<crate::pages::Message> {
row::with_capacity(3)
.align_items(iced::Alignment::Center)
.spacing(theme.cosmic().space_s())
.push(&*descriptions[2])
.push(widget::text::body(&descriptions[short]))
.push(delay_slider)
.push(&*descriptions[3])
.push(widget::text::body(&descriptions[long]))
}))
.add(settings::flex_item(&*descriptions[1], {
.add(settings::flex_item(&descriptions[repeat_rate], {
// Repeat rate
let rate_slider = cosmic::widget::slider(
KB_REPEAT_RATE_MIN..=KB_REPEAT_RATE_MAX,
@ -689,9 +698,9 @@ fn keyboard_typing_assist() -> Section<crate::pages::Message> {
row::with_capacity(3)
.align_items(iced::Alignment::Center)
.spacing(theme.cosmic().space_s())
.push(&*descriptions[4])
.push(widget::text::body(&descriptions[slow]))
.push(rate_slider)
.push(&*descriptions[5])
.push(widget::text::body(&descriptions[fast]))
}))
.apply(cosmic::Element::from)
.map(crate::pages::Message::Keyboard)

View file

@ -2,6 +2,7 @@ use cosmic::widget::{column, settings};
use cosmic::{Apply, Element};
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slab::Slab;
use slotmap::SlotMap;
#[derive(Default)]
@ -27,9 +28,11 @@ impl page::Page<crate::pages::Message> for Page {
impl page::AutoBind<crate::pages::Message> for Page {}
fn shortcuts() -> Section<crate::pages::Message> {
let descriptions = Slab::new();
Section::default()
.descriptions(vec![])
.view::<Page>(|_binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
// TODO need something more custom
/*
settings::view_section(&section.title)

View file

@ -14,17 +14,6 @@ pub mod keyboard;
pub mod mouse;
pub mod touchpad;
crate::cache_dynamic_lazy! {
static ACCELERATION_DESC: String = fl!("acceleration-desc");
static DISABLE_WHILE_TYPING: String = fl!("disable-while-typing");
static PRIMARY_BUTTON: String = fl!("primary-button");
static SCROLLING_EDGE: String = fl!("scrolling", "edge");
static SCROLLING_NATURAL_DESC: String = fl!("scrolling", "natural-desc");
static SCROLLING_NATURAL: String = fl!("scrolling", "natural");
static SCROLLING_SPEED: String = fl!("scrolling", "speed");
static SCROLLING_TWO_FINGER: String = fl!("scrolling", "two-finger");
}
#[derive(Clone, Debug)]
pub enum Message {
// seperate close message, to make sure another isn't closed?

View file

@ -4,15 +4,11 @@ use cosmic::{Apply, Element};
use cosmic_comp_config::input::AccelProfile;
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slab::Slab;
use slotmap::SlotMap;
use super::Message;
crate::cache_dynamic_lazy! {
static MOUSE_ACCELERATION: String = fl!("mouse", "acceleration");
static MOUSE_SPEED: String = fl!("mouse", "speed");
}
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")))
@ -43,48 +39,53 @@ impl page::Page<crate::pages::Message> for Page {
impl page::AutoBind<crate::pages::Message> for Page {}
fn mouse() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let mouse_acceleration = descriptions.insert(fl!("mouse", "acceleration"));
let mouse_speed = descriptions.insert(fl!("mouse", "speed"));
let primary_button = descriptions.insert(fl!("primary-button"));
let acceleration_desc = descriptions.insert(fl!("acceleration-desc"));
Section::default()
.descriptions(vec![
super::PRIMARY_BUTTON.as_str().into(),
MOUSE_SPEED.as_str().into(),
MOUSE_ACCELERATION.as_str().into(),
super::ACCELERATION_DESC.as_str().into(),
])
.view::<Page>(|binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |binder, _page, section| {
let descriptions = &section.descriptions;
let input = binder.page::<super::Page>().expect("input page not found");
let theme = cosmic::theme::active();
settings::view_section(&section.title)
.add(settings::flex_item(
&*super::PRIMARY_BUTTON,
&descriptions[primary_button],
cosmic::widget::segmented_control::horizontal(&input.primary_button)
.minimum_button_width(0)
.on_activate(|x| Message::PrimaryButtonSelected(x, false)),
))
.add(settings::item::builder(&*MOUSE_SPEED).flex_control({
let value = (input
.input_default
.acceleration
.as_ref()
.map_or(0.0, |x| x.speed)
+ 1.0)
* 50.0;
let slider = widget::slider(10.0..=80.0, value, |value| {
Message::SetMouseSpeed((value / 50.0) - 1.0, false)
})
.width(250.0)
.breakpoints(&[45.0]);
row::with_capacity(2)
.align_items(Alignment::Center)
.spacing(theme.cosmic().space_s())
.push(text(format!("{:.0}", value.round())))
.push(slider)
}))
.add(
settings::item::builder(&*MOUSE_ACCELERATION)
.description(&*super::ACCELERATION_DESC)
settings::item::builder(&descriptions[mouse_speed]).flex_control({
let value = (input
.input_default
.acceleration
.as_ref()
.map_or(0.0, |x| x.speed)
+ 1.0)
* 50.0;
let slider = widget::slider(10.0..=80.0, value, |value| {
Message::SetMouseSpeed((value / 50.0) - 1.0, false)
})
.width(250.0)
.breakpoints(&[45.0]);
row::with_capacity(2)
.align_items(Alignment::Center)
.spacing(theme.cosmic().space_s())
.push(text(format!("{:.0}", value.round())))
.push(slider)
}),
)
.add(
settings::item::builder(&descriptions[mouse_acceleration])
.description(&descriptions[acceleration_desc])
.toggler(
input
.input_default
@ -100,19 +101,22 @@ fn mouse() -> Section<crate::pages::Message> {
}
fn scrolling() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let natural = descriptions.insert(fl!("scrolling", "natural"));
let natural_desc = descriptions.insert(fl!("scrolling", "natural-desc"));
let scroll_speed = descriptions.insert(fl!("scrolling", "speed"));
Section::default()
.title(fl!("scrolling"))
.descriptions(vec![
super::SCROLLING_SPEED.as_str().into(),
super::SCROLLING_NATURAL.as_str().into(),
super::SCROLLING_NATURAL_DESC.as_str().into(),
])
.view::<Page>(|binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |binder, _page, section| {
let descriptions = &section.descriptions;
let input = binder.page::<super::Page>().expect("input page not found");
let theme = cosmic::theme::active();
settings::view_section(&section.title)
.add(settings::flex_item(&*super::SCROLLING_SPEED, {
.add(settings::flex_item(&descriptions[scroll_speed], {
let value = input
.input_default
.scroll_config
@ -136,8 +140,8 @@ fn scrolling() -> Section<crate::pages::Message> {
.push(slider)
}))
.add(
settings::item::builder(&*super::SCROLLING_NATURAL)
.description(&*super::SCROLLING_NATURAL_DESC)
settings::item::builder(&descriptions[natural])
.description(&descriptions[natural_desc])
.toggler(
input
.input_default

View file

@ -4,32 +4,11 @@ use cosmic::{Apply, Element};
use cosmic_comp_config::input::{AccelProfile, ClickMethod, ScrollMethod};
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slab::Slab;
use slotmap::SlotMap;
use super::Message;
crate::cache_dynamic_lazy! {
static CLICK_BEHAVIOR_CLICK_FINGER: String = fl!("click-behavior", "click-finger");
static CLICK_BEHAVIOR_BUTTON_AREAS: String = fl!("click-behavior", "button-areas");
static TAP_TO_CLICK: String = fl!("tap-to-click");
static TAP_TO_CLICK_DESC: String = fl!("tap-to-click", "desc");
static TOUCHPAD_ACCELERAION: String = fl!("touchpad", "acceleration");
static TOUCHPAD_SPEED: String = fl!("touchpad", "speed");
static OPEN_APPLICATION_LIBRARY: String = fl!("open-application-library");
static OPEN_WORKSPACES_VIEW: String = fl!("open-workspaces-view");
static SWIPING_FOUR_FINGER_DOWN: String = fl!("gestures", "four-finger-down");
static SWIPING_FOUR_FINGER_LEFT: String = fl!("gestures", "four-finger-left");
static SWIPING_FOUR_FINGER_RIGHT: String = fl!("gestures", "four-finger-right");
static SWIPING_FOUR_FINGER_UP: String = fl!("gestures", "four-finger-up");
static SWIPING_THREE_FINGER_ANY: String = fl!("gestures", "three-finger-any");
static SWITCH_BETWEEN_WINDOWS: String = fl!("switch-between-windows");
static SWITCH_TO_NEXT_WORKSPACE: String = fl!("switch-to-next-workspace");
static SWITCH_TO_PREV_WORKSPACE: String = fl!("switch-to-prev-workspace");
}
#[derive(Default)]
pub struct Page;
@ -56,49 +35,54 @@ impl page::Page<crate::pages::Message> for Page {
impl page::AutoBind<crate::pages::Message> for Page {}
fn touchpad() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let primary_button = descriptions.insert(fl!("primary-button"));
let touchpad_speed = descriptions.insert(fl!("touchpad", "speed"));
let acceleration = descriptions.insert(fl!("touchpad", "acceleration"));
let acceleration_desc = descriptions.insert(fl!("acceleration-desc"));
let disable_while_typing = descriptions.insert(fl!("disable-while-typing"));
Section::default()
.descriptions(vec![
super::PRIMARY_BUTTON.as_str().into(),
TOUCHPAD_SPEED.as_str().into(),
TOUCHPAD_ACCELERAION.as_str().into(),
super::ACCELERATION_DESC.as_str().into(),
super::DISABLE_WHILE_TYPING.as_str().into(),
])
.view::<Page>(|binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |binder, _page, section| {
let descriptions = &section.descriptions;
let input = binder.page::<super::Page>().expect("input page not found");
let theme = cosmic::theme::active();
settings::view_section(&section.title)
.add(settings::flex_item(
&*super::PRIMARY_BUTTON,
&descriptions[primary_button],
cosmic::widget::segmented_control::horizontal(&input.touchpad_primary_button)
.minimum_button_width(0)
.on_activate(|x| Message::PrimaryButtonSelected(x, true)),
))
.add(settings::item::builder(&*TOUCHPAD_SPEED).flex_control({
let value = (input
.input_touchpad
.acceleration
.as_ref()
.map_or(0.0, |x| x.speed)
+ 1.0)
* 50.0;
let slider = widget::slider(10.0..=80.0, value, |value| {
Message::SetMouseSpeed((value / 50.0) - 1.0, true)
})
.width(250.0)
.breakpoints(&[45.0]);
row::with_capacity(2)
.align_items(Alignment::Center)
.spacing(theme.cosmic().space_s())
.push(text(format!("{:.0}", value.round())))
.push(slider)
}))
.add(
settings::item::builder(&*TOUCHPAD_ACCELERAION)
.description(&*super::ACCELERATION_DESC)
settings::item::builder(&descriptions[touchpad_speed]).flex_control({
let value = (input
.input_touchpad
.acceleration
.as_ref()
.map_or(0.0, |x| x.speed)
+ 1.0)
* 50.0;
let slider = widget::slider(10.0..=80.0, value, |value| {
Message::SetMouseSpeed((value / 50.0) - 1.0, true)
})
.width(250.0)
.breakpoints(&[45.0]);
row::with_capacity(2)
.align_items(Alignment::Center)
.spacing(theme.cosmic().space_s())
.push(text(format!("{:.0}", value.round())))
.push(slider)
}),
)
.add(
settings::item::builder(&descriptions[acceleration])
.description(&descriptions[acceleration_desc])
.toggler(
input
.input_touchpad
@ -109,7 +93,7 @@ fn touchpad() -> Section<crate::pages::Message> {
),
)
.add(
settings::item::builder(&*super::DISABLE_WHILE_TYPING).toggler(
settings::item::builder(&descriptions[disable_while_typing]).toggler(
input.input_touchpad.disable_while_typing.unwrap_or(false),
|enabled| Message::DisableWhileTyping(enabled, true),
),
@ -120,15 +104,18 @@ fn touchpad() -> Section<crate::pages::Message> {
}
fn click_behavior() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let click_finger = descriptions.insert(fl!("click-behavior", "click-finger"));
let button_areas = descriptions.insert(fl!("click-behavior", "button-areas"));
let tap_to_click = descriptions.insert(fl!("tap-to-click"));
let _tap_to_click_desc = descriptions.insert(fl!("tap-to-click", "desc"));
Section::default()
.title(fl!("click-behavior"))
.descriptions(vec![
CLICK_BEHAVIOR_CLICK_FINGER.as_str().into(),
CLICK_BEHAVIOR_BUTTON_AREAS.as_str().into(),
TAP_TO_CLICK.as_str().into(),
TAP_TO_CLICK_DESC.as_str().into(),
])
.view::<Page>(|binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |binder, _page, section| {
let descriptions = &section.descriptions;
let page = binder
.page::<super::Page>()
.expect("input devices page not found");
@ -136,7 +123,7 @@ fn click_behavior() -> Section<crate::pages::Message> {
settings::view_section(&*section.title)
// Secondary click via two fingers, and middle-click via three fingers
.add(settings::item_row(vec![widget::radio(
&*CLICK_BEHAVIOR_CLICK_FINGER,
&descriptions[click_finger],
ClickMethod::Clickfinger,
page.input_touchpad.click_method,
|option| Message::SetSecondaryClickBehavior(Some(option), true),
@ -144,14 +131,14 @@ fn click_behavior() -> Section<crate::pages::Message> {
.into()]))
// Secondary and middle-click via button areas.
.add(settings::item_row(vec![widget::radio(
&*CLICK_BEHAVIOR_BUTTON_AREAS,
&descriptions[button_areas],
ClickMethod::ButtonAreas,
page.input_touchpad.click_method,
|option| Message::SetSecondaryClickBehavior(Some(option), true),
)
.into()]))
.add(
settings::item::builder(&*TAP_TO_CLICK).toggler(
settings::item::builder(&descriptions[tap_to_click]).toggler(
page.input_touchpad
.tap_config
.as_ref()
@ -165,16 +152,19 @@ fn click_behavior() -> Section<crate::pages::Message> {
}
fn scrolling() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let edge = descriptions.insert(fl!("scrolling", "edge"));
let natural = descriptions.insert(fl!("scrolling", "natural"));
let natural_desc = descriptions.insert(fl!("scrolling", "natural-desc"));
let scroll_speed = descriptions.insert(fl!("scrolling", "speed"));
let two_finger = descriptions.insert(fl!("scrolling", "two-finger"));
Section::default()
.title(fl!("scrolling"))
.descriptions(vec![
super::SCROLLING_TWO_FINGER.as_str().into(),
super::SCROLLING_EDGE.as_str().into(),
super::SCROLLING_SPEED.as_str().into(),
super::SCROLLING_NATURAL.as_str().into(),
super::SCROLLING_NATURAL_DESC.as_str().into(),
])
.view::<Page>(|binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |binder, _page, section| {
let descriptions = &section.descriptions;
let page = binder
.page::<super::Page>()
.expect("input devices page not found");
@ -183,7 +173,7 @@ fn scrolling() -> Section<crate::pages::Message> {
settings::view_section(&section.title)
// Two-finger scrolling toggle
.add(settings::item_row(vec![widget::radio(
&*super::SCROLLING_TWO_FINGER,
&descriptions[two_finger],
ScrollMethod::TwoFinger,
page.input_touchpad
.scroll_config
@ -194,7 +184,7 @@ fn scrolling() -> Section<crate::pages::Message> {
.into()]))
// Edge scrolling toggle
.add(settings::item_row(vec![widget::radio(
&*super::SCROLLING_EDGE,
&descriptions[edge],
ScrollMethod::Edge,
page.input_touchpad
.scroll_config
@ -204,7 +194,7 @@ fn scrolling() -> Section<crate::pages::Message> {
)
.into()]))
// Scroll speed slider
.add(settings::item(&*super::SCROLLING_SPEED, {
.add(settings::item(&descriptions[scroll_speed], {
let value = page
.input_touchpad
.scroll_config
@ -229,8 +219,8 @@ fn scrolling() -> Section<crate::pages::Message> {
}))
// Natural scrolling toggle
.add(
settings::item::builder(&*super::SCROLLING_NATURAL)
.description(&*super::SCROLLING_NATURAL_DESC)
settings::item::builder(&descriptions[natural])
.description(&descriptions[natural_desc])
.toggler(
page.input_touchpad
.scroll_config
@ -245,36 +235,46 @@ fn scrolling() -> Section<crate::pages::Message> {
}
fn swiping() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let four_finger_down = descriptions.insert(fl!("gestures", "four-finger-down"));
// let four_finger_left = descriptions.insert(fl!("gestures", "four-finger-left"));
// let four_finger_right = descriptions.insert(fl!("gestures", "four-finger-right"));
let four_finger_up = descriptions.insert(fl!("gestures", "four-finger-up"));
// let three_finger_any = descriptions.insert(fl!("gestures", "three-finger-any"));
// let open_application_library = descriptions.insert(fl!("open-application-library"));
// let open_workspaces_view = descriptions.insert(fl!("open-workspaces-view"));
// let switch_between_windows = descriptions.insert(fl!("switch-between-windows"));
let switch_to_next_workspace = descriptions.insert(fl!("switch-to-next-workspace"));
let switch_to_prev_workspace = descriptions.insert(fl!("switch-to-prev-workspace"));
Section::default()
.title(fl!("gestures"))
.descriptions(vec![
SWIPING_FOUR_FINGER_DOWN.as_str().into(),
SWIPING_FOUR_FINGER_LEFT.as_str().into(),
SWIPING_FOUR_FINGER_RIGHT.as_str().into(),
SWIPING_FOUR_FINGER_UP.as_str().into(),
SWIPING_THREE_FINGER_ANY.as_str().into(),
])
.view::<Page>(|_binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
let descriptions = &section.descriptions;
settings::view_section(&*section.title)
// .add(
// settings::item::builder(&*SWIPING_THREE_FINGER_ANY)
// .flex_control(text(&*SWITCH_BETWEEN_WINDOWS)),
// settings::item::builder(&descriptions[three_finger_any])
// .flex_control(text(&descriptions[switch_between_windows])),
// )
.add(
settings::item::builder(&*SWIPING_FOUR_FINGER_UP)
.flex_control(text(&*SWITCH_TO_PREV_WORKSPACE)),
settings::item::builder(&descriptions[four_finger_up])
.flex_control(text(&descriptions[switch_to_prev_workspace])),
)
.add(
settings::item::builder(&*SWIPING_FOUR_FINGER_DOWN)
.flex_control(text(&*SWITCH_TO_NEXT_WORKSPACE)),
settings::item::builder(&descriptions[four_finger_down])
.flex_control(text(&descriptions[switch_to_next_workspace])),
)
// .add(
// settings::item::builder(&*SWIPING_FOUR_FINGER_LEFT)
// .flex_control(text(&*OPEN_WORKSPACES_VIEW)),
// settings::item::builder(&descriptions[four_finger_left])
// .flex_control(text(&descriptions[open_workspaces_view])),
// )
// .add(
// settings::item::builder(&*SWIPING_FOUR_FINGER_RIGHT)
// .flex_control(text(&*OPEN_APPLICATION_LIBRARY)),
// settings::item::builder(&descriptions[four_finger_right])
// .flex_control(text(&descriptions[open_application_library])),
// )
.apply(Element::from)
.map(crate::pages::Message::Input)

View file

@ -109,15 +109,15 @@ impl SetPowerProfile for S76Backend {
match profile {
PowerProfile::Battery => match daemon.battery().await {
Ok(x) => tracing::info!("Battery mode activated."),
Ok(()) => tracing::info!("Battery mode activated."),
Err(e) => tracing::error!("{e}"),
},
PowerProfile::Balanced => match daemon.balanced().await {
Ok(x) => tracing::info!("Balanced mode activated."),
Ok(()) => tracing::info!("Balanced mode activated."),
Err(e) => tracing::error!("{e}"),
},
PowerProfile::Performance => match daemon.performance().await {
Ok(x) => tracing::info!("Performance mode activated."),
Ok(()) => tracing::info!("Performance mode activated."),
Err(e) => tracing::error!("{e}"),
},
}
@ -181,15 +181,15 @@ impl SetPowerProfile for PPBackend {
match profile {
PowerProfile::Battery => match daemon.set_active_profile("power-saver").await {
Ok(x) => tracing::info!("Battery mode activated."),
Ok(()) => tracing::info!("Battery mode activated."),
Err(e) => tracing::error!("{e}"),
},
PowerProfile::Balanced => match daemon.set_active_profile("balanced").await {
Ok(x) => tracing::info!("Balanced mode activated."),
Ok(()) => tracing::info!("Balanced mode activated."),
Err(e) => tracing::error!("{e}"),
},
PowerProfile::Performance => match daemon.set_active_profile("performance").await {
Ok(x) => tracing::info!("Performance mode activated."),
Ok(()) => tracing::info!("Performance mode activated."),
Err(e) => tracing::error!("{e}"),
},
}

View file

@ -1,13 +1,13 @@
mod backend;
use self::backend::{GetCurrentPowerProfile, SetPowerProfile};
use backend::PowerProfile;
use cosmic::widget;
use cosmic::{widget::settings, Apply};
use cosmic_settings_page::{self as page, section, Section};
use slab::Slab;
use slotmap::SlotMap;
use self::backend::{GetCurrentPowerProfile, SetPowerProfile};
mod backend;
#[derive(Default)]
pub struct Page;
@ -48,10 +48,14 @@ impl Page {
}
fn profiles() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let _power_desc = descriptions.insert(fl!("power", "desc"));
Section::default()
.title(fl!("power-mode"))
.descriptions(vec![fl!("power", "desc").into()])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
let mut section = settings::view_section(&section.title);
let runtime = tokio::runtime::Runtime::new().unwrap();

View file

@ -3,25 +3,9 @@
use cosmic::widget::{settings, text};
use cosmic_settings_page::{self as page, section, Section};
use slab::Slab;
use slotmap::SlotMap;
// crate::cache_dynamic_lazy! {
// pub static SOUND_ALERTS_VOLUME: String = fl!("sound-alerts", "volume");
// pub static SOUND_ALERTS_SOUND: String = fl!("sound-alerts", "sound");
// pub static SOUND_APPLICATIONS_DESC: String = fl!("sound-applications", "desc");
// pub static SOUND_INPUT_VOLUME: String = fl!("sound-input", "volume");
// pub static SOUND_INPUT_DEVICE: String = fl!("sound-input", "device");
// pub static SOUND_INPUT_LEVEL: String = fl!("sound-input", "level");
// pub static SOUND_OUTPUT_VOLUME: String = fl!("sound-output", "volume");
// pub static SOUND_OUTPUT_DEVICE: String = fl!("sound-output", "device");
// pub static SOUND_OUTPUT_LEVEL: String = fl!("sound-output", "level");
// pub static SOUND_OUTPUT_CONFIG: String = fl!("sound-output", "config");
// pub static SOUND_OUTPUT_BALANCE: String = fl!("sound-output", "balance");
// }
#[derive(Default)]
pub struct Page;
@ -48,64 +32,76 @@ impl page::Page<crate::pages::Message> for Page {
impl page::AutoBind<crate::pages::Message> for Page {}
fn alerts() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let volume = descriptions.insert(fl!("sound-alerts", "volume"));
let sound = descriptions.insert(fl!("sound-alerts", "sound"));
Section::default()
.title(fl!("sound-alerts"))
.descriptions(vec![
fl!("sound-alerts", "volume").into(),
fl!("sound-alerts", "sound").into(),
])
.view::<Page>(|_binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
settings::view_section(&section.title)
.add(settings::item(&*section.descriptions[0], text("TODO")))
.add(settings::item(&*section.descriptions[1], text("TODO")))
.add(settings::item(&section.descriptions[volume], text("TODO")))
.add(settings::item(&section.descriptions[sound], text("TODO")))
.into()
})
}
fn applications() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let applications = descriptions.insert(fl!("sound-applications", "desc"));
Section::default()
.title(fl!("sound-applications"))
.descriptions(vec![fl!("sound-applications", "desc").into()])
.view::<Page>(|_binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
settings::view_section(&section.title)
.add(settings::item(&*section.descriptions[0], text("TODO")))
.add(settings::item(
&*section.descriptions[applications],
text("TODO"),
))
.into()
})
}
fn input() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let volume = descriptions.insert(fl!("sound-input", "volume"));
let device = descriptions.insert(fl!("sound-input", "device"));
let level = descriptions.insert(fl!("sound-input", "level"));
Section::default()
.title(fl!("sound-input"))
.descriptions(vec![
fl!("sound-input", "volume").into(),
fl!("sound-input", "device").into(),
fl!("sound-input", "level").into(),
])
.view::<Page>(|_binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
settings::view_section(&section.title)
.add(settings::item(&*section.descriptions[0], text("TODO")))
.add(settings::item(&*section.descriptions[1], text("TODO")))
.add(settings::item(&*section.descriptions[2], text("TODO")))
.add(settings::item(&*section.descriptions[volume], text("TODO")))
.add(settings::item(&*section.descriptions[device], text("TODO")))
.add(settings::item(&*section.descriptions[level], text("TODO")))
.into()
})
}
fn output() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let volume = descriptions.insert(fl!("sound-output", "volume"));
let device = descriptions.insert(fl!("sound-output", "device"));
let level = descriptions.insert(fl!("sound-output", "level"));
let config = descriptions.insert(fl!("sound-output", "config"));
// let balance = descriptions.insert(fl!("sound-output", "balance"));
Section::default()
.title(fl!("sound-output"))
.descriptions(vec![
fl!("sound-output", "volume").into(),
fl!("sound-output", "device").into(),
fl!("sound-output", "level").into(),
fl!("sound-output", "config").into(),
fl!("sound-output", "balance").into(),
])
.view::<Page>(|_binder, _page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
settings::view_section(&section.title)
.add(settings::item(&*section.descriptions[0], text("TODO")))
.add(settings::item(&*section.descriptions[1], text("TODO")))
.add(settings::item(&*section.descriptions[2], text("TODO")))
.add(settings::item(&*section.descriptions[3], text("TODO")))
.add(settings::item(&*section.descriptions[volume], text("TODO")))
.add(settings::item(&*section.descriptions[device], text("TODO")))
.add(settings::item(&*section.descriptions[level], text("TODO")))
.add(settings::item(&*section.descriptions[config], text("TODO")))
.into()
})
}

View file

@ -1,12 +1,12 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic::iced::Length;
use cosmic_settings_page::{self as page, section, Section};
use cosmic::widget::{self, editable_input, list_column, settings, text};
use cosmic::widget::{editable_input, list_column, settings, text};
use cosmic::{command, Apply, Command};
use cosmic_settings_system::about::Info;
use slab::Slab;
use slotmap::SlotMap;
#[derive(Clone, Debug)]
@ -105,12 +105,14 @@ impl Page {
}
fn device() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let device = descriptions.insert(fl!("about-device"));
let device_desc = descriptions.insert(fl!("about-device", "desc"));
Section::default()
.descriptions(vec![
fl!("about-device").into(),
fl!("about-device", "desc").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let desc = &section.descriptions;
let hostname_input = editable_input(
@ -122,8 +124,8 @@ fn device() -> Section<crate::pages::Message> {
.on_input(Message::HostnameInput)
.on_submit(Message::HostnameSubmit);
let device_name = settings::item::builder(&*desc[0])
.description(&*desc[1])
let device_name = settings::item::builder(&*desc[device])
.description(&*desc[device_desc])
.flex_control(hostname_input);
list_column()
@ -134,33 +136,38 @@ fn device() -> Section<crate::pages::Message> {
}
fn hardware() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let model = descriptions.insert(fl!("about-hardware", "model"));
let memory = descriptions.insert(fl!("about-hardware", "memory"));
let processor = descriptions.insert(fl!("about-hardware", "processor"));
let graphics = descriptions.insert(fl!("about-hardware", "graphics"));
let disk_capacity = descriptions.insert(fl!("about-hardware", "disk-capacity"));
Section::default()
.title(fl!("about-hardware"))
.descriptions(vec![
fl!("about-hardware", "model").into(),
fl!("about-hardware", "memory").into(),
fl!("about-hardware", "processor").into(),
fl!("about-hardware", "graphics").into(),
fl!("about-hardware", "disk-capacity").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let desc = &section.descriptions;
let mut sections = settings::view_section(&section.title)
.add(settings::flex_item(
&*desc[0],
&*desc[model],
text(&page.info.hardware_model),
))
.add(settings::flex_item(&*desc[1], text(&page.info.memory)))
.add(settings::flex_item(&*desc[2], text(&page.info.processor)));
.add(settings::flex_item(&*desc[memory], text(&page.info.memory)))
.add(settings::flex_item(
&*desc[processor],
text(&page.info.processor),
));
for card in &page.info.graphics {
sections = sections.add(settings::flex_item(&*desc[3], text(card.as_str())));
sections = sections.add(settings::flex_item(&*desc[graphics], text(card.as_str())));
}
sections
.add(settings::flex_item(
&*desc[4],
&*desc[disk_capacity],
text(&page.info.disk_capacity),
))
.into()
@ -168,31 +175,33 @@ fn hardware() -> Section<crate::pages::Message> {
}
fn os() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let os = descriptions.insert(fl!("about-os", "os"));
let os_arch = descriptions.insert(fl!("about-os", "os-architecture"));
let desktop = descriptions.insert(fl!("about-os", "desktop-environment"));
let windowing_system = descriptions.insert(fl!("about-os", "windowing-system"));
Section::default()
.title(fl!("about-os"))
.descriptions(vec![
fl!("about-os", "os").into(),
fl!("about-os", "os-architecture").into(),
fl!("about-os", "desktop-environment").into(),
fl!("about-os", "windowing-system").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let desc = &section.descriptions;
settings::view_section(&section.title)
.add(settings::flex_item(
&*desc[0],
&*desc[os],
text(&page.info.operating_system),
))
.add(settings::flex_item(
&*desc[1],
&*desc[os_arch],
text(&page.info.os_architecture),
))
.add(settings::flex_item(
&*desc[2],
&*desc[desktop],
text(&page.info.desktop_environment),
))
.add(settings::flex_item(
&*desc[3],
&*desc[windowing_system],
text(&page.info.windowing_system),
))
.into()
@ -204,7 +213,7 @@ fn os() -> Section<crate::pages::Message> {
// Section::default()
// .title(fl!("about-related"))
// .descriptions(vec![fl!("about-related", "support").into()])
// .view::<Page>(|_binder, _page, section| {
// .view::<Page>(move |_binder, _page, section| {
// settings::view_section(&section.title)
// .add(settings::item(&*section.descriptions[0], text("TODO")))
// .into()

View file

@ -9,16 +9,12 @@ use cosmic::{
};
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
// use icu::calendar::{DateTime, Gregorian};
use slab::Slab;
use slotmap::SlotMap;
use tracing::error;
crate::cache_dynamic_lazy! {
static TIME_FORMAT_TWENTY_FOUR: String = fl!("time-format", "twenty-four");
static TIME_FORMAT_FIRST: String = fl!("time-format", "first");
static TIME_FORMAT_SHOW_DATE: String = fl!("time-format", "show-date");
static TIME_FORMAT_WEEKDAYS: [String; 4] = [fl!("time-format", "friday"), fl!("time-format", "saturday"), fl!("time-format", "sunday"), fl!("time-format", "monday")];
static WEEKDAYS: [String; 4] = [fl!("time-format", "friday"), fl!("time-format", "saturday"), fl!("time-format", "sunday"), fl!("time-format", "monday")];
}
pub struct Page {
@ -28,7 +24,6 @@ pub struct Page {
military_time: bool,
first_day_of_week: usize,
show_date_in_top_panel: bool,
// info: Option<cosmic_settings_time::Info>,
}
impl Default for Page {
@ -115,20 +110,22 @@ pub enum Message {
impl page::AutoBind<crate::pages::Message> for Page {}
fn date() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let auto = descriptions.insert(fl!("time-date", "auto"));
let title = descriptions.insert(fl!("time-date"));
Section::default()
.title(fl!("time-date"))
.descriptions(vec![
fl!("time-date", "auto").into(),
fl!("time-date").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
settings::view_section(&section.title)
.add(
settings::item::builder(&*section.descriptions[0])
settings::item::builder(&*section.descriptions[auto])
.toggler(page.auto, Message::Automatic),
)
.add(settings::item(
&*section.descriptions[1],
&*section.descriptions[title],
horizontal_space(Length::Fill),
))
.apply(cosmic::Element::from)
@ -137,24 +134,26 @@ fn date() -> Section<crate::pages::Message> {
}
fn format() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let military = descriptions.insert(fl!("time-format", "twenty-four"));
let first = descriptions.insert(fl!("time-format", "first"));
let show_date = descriptions.insert(fl!("time-format", "show-date"));
Section::default()
.title(fl!("time-format"))
.descriptions(vec![
TIME_FORMAT_TWENTY_FOUR.as_str().into(),
TIME_FORMAT_FIRST.as_str().into(),
TIME_FORMAT_SHOW_DATE.as_str().into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
settings::view_section(&section.title)
// 24-hour toggle
.add(
settings::item::builder(&*TIME_FORMAT_TWENTY_FOUR)
settings::item::builder(&section.descriptions[military])
.toggler(page.military_time, Message::MilitaryTime),
)
// First day of week
.add(
settings::item::builder(&*TIME_FORMAT_FIRST).flex_control(dropdown(
&*TIME_FORMAT_WEEKDAYS,
settings::item::builder(&section.descriptions[first]).flex_control(dropdown(
&*WEEKDAYS,
match page.first_day_of_week {
4 => Some(0), // friday
5 => Some(1), // saturday
@ -173,7 +172,7 @@ fn format() -> Section<crate::pages::Message> {
)
// Date on top panel toggle
.add(
settings::item::builder(&*TIME_FORMAT_SHOW_DATE)
settings::item::builder(&section.descriptions[show_date])
.toggler(page.show_date_in_top_panel, Message::ShowDate),
)
.apply(cosmic::Element::from)
@ -182,24 +181,26 @@ fn format() -> Section<crate::pages::Message> {
}
fn timezone() -> Section<crate::pages::Message> {
let mut descriptions = Slab::new();
let auto = descriptions.insert(fl!("time-zone", "auto"));
let auto_info = descriptions.insert(fl!("time-zone", "auto-info"));
let time_zone = descriptions.insert(fl!("time-zone"));
Section::default()
.title(fl!("time-zone"))
.descriptions(vec![
fl!("time-zone", "auto").into(),
fl!("time-zone", "auto-info").into(),
fl!("time-zone").into(),
])
.view::<Page>(|_binder, page, section| {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
settings::view_section(&section.title)
// Automatic timezone toggle
.add(
settings::item::builder(&*section.descriptions[0])
.description(&*section.descriptions[1])
settings::item::builder(&*section.descriptions[auto])
.description(&*section.descriptions[auto_info])
.toggler(page.auto_timezone, Message::AutomaticTimezone),
)
// Time zone select
.add(
settings::item::builder(&*section.descriptions[2])
settings::item::builder(&*section.descriptions[time_zone])
.control(horizontal_space(Length::Fill)),
)
.apply(cosmic::Element::from)

View file

@ -3,8 +3,7 @@
use cosmic::iced::Length;
use cosmic::widget::{
button, column, container, divider, horizontal_space, icon, list, row, settings, text,
vertical_space,
button, column, container, divider, horizontal_space, icon, row, settings, text, vertical_space,
};
use cosmic::{theme, Apply, Element};
use cosmic_settings_page as page;

View file

@ -12,4 +12,5 @@ generator = "0.7.5"
downcast-rs = "1.2.0"
once_cell = "1.19.0"
tokio.workspace = true
url = "2.5.0"
url = "2.5.0"
slab = "0.4.9"

View file

@ -3,7 +3,7 @@
use derive_setters::Setters;
use regex::Regex;
use std::borrow::Cow;
use slab::Slab;
use crate::{Binder, Page};
@ -31,7 +31,7 @@ pub struct Section<Message> {
#[setters(into)]
pub title: String,
#[setters(into)]
pub descriptions: Vec<Cow<'static, str>>,
pub descriptions: Slab<String>,
#[setters(skip)]
pub show_while: Option<ShowWhileFn<Message>>,
#[setters(skip)]
@ -44,7 +44,7 @@ impl<Message: 'static> Default for Section<Message> {
fn default() -> Self {
Self {
title: String::new(),
descriptions: Vec::new(),
descriptions: Slab::new(),
show_while: None,
view_fn: Box::new(unimplemented),
search_ignore: false,
@ -63,7 +63,7 @@ impl<Message: 'static> Section<Message> {
return true;
}
for description in &*self.descriptions {
for (_, description) in &self.descriptions {
if rule.is_match(description) {
return true;
}