From f6e50f1d9b41c4b37ca5c23d28e4ecf40113f152 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Thu, 6 Jun 2024 15:52:21 +0200 Subject: [PATCH] refactor: use Slab for storing page section descriptions --- Cargo.lock | 2 + cosmic-settings/Cargo.toml | 1 + .../src/pages/desktop/appearance.rs | 135 ++++---- .../src/pages/desktop/dock/applets.rs | 2 +- cosmic-settings/src/pages/desktop/dock/mod.rs | 11 +- cosmic-settings/src/pages/desktop/options.rs | 39 ++- .../src/pages/desktop/panel/inner.rs | 69 ++-- .../src/pages/desktop/wallpaper/mod.rs | 35 +- .../src/pages/desktop/workspaces.rs | 33 +- cosmic-settings/src/pages/display/mod.rs | 299 +++++++++--------- cosmic-settings/src/pages/display/text.rs | 36 --- .../src/pages/input/keyboard/mod.rs | 61 ++-- .../src/pages/input/keyboard/shortcuts.rs | 7 +- cosmic-settings/src/pages/input/mod.rs | 11 - cosmic-settings/src/pages/input/mouse.rs | 94 +++--- cosmic-settings/src/pages/input/touchpad.rs | 192 +++++------ .../src/pages/power/backend/mod.rs | 12 +- cosmic-settings/src/pages/power/mod.rs | 16 +- cosmic-settings/src/pages/sound.rs | 92 +++--- cosmic-settings/src/pages/system/about.rs | 77 +++-- cosmic-settings/src/pages/time/date.rs | 67 ++-- cosmic-settings/src/widget/mod.rs | 3 +- page/Cargo.toml | 3 +- page/src/section.rs | 8 +- 24 files changed, 666 insertions(+), 639 deletions(-) delete mode 100644 cosmic-settings/src/pages/display/text.rs diff --git a/Cargo.lock b/Cargo.lock index d66da64..5767038 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/cosmic-settings/Cargo.toml b/cosmic-settings/Cargo.toml index 67e74ca..1becf66 100644 --- a/cosmic-settings/Cargo.toml +++ b/cosmic-settings/Cargo.toml @@ -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" diff --git a/cosmic-settings/src/pages/desktop/appearance.rs b/cosmic-settings/src/pages/desktop/appearance.rs index 70e3fe1..840889e 100644 --- a/cosmic-settings/src/pages/desktop/appearance.rs +++ b/cosmic-settings/src/pages/desktop/appearance.rs @@ -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; -type IconHandles = Vec<[icon::Handle; ICON_PREV_N]>; + +pub type IconThemes = Vec; +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 for Page { #[allow(clippy::too_many_lines)] pub fn mode_and_colors() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let descriptions = §ion.descriptions; let palette = &page.theme_builder.palette.as_ref(); let cur_accent = page @@ -1182,7 +1175,7 @@ pub fn mode_and_colors() -> Section { .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 { .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 { .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 { ) .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 { .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 { ), ) .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 { }), ) .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 { ), ) .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 { ), ) .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 { #[allow(clippy::too_many_lines)] pub fn style() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let descriptions = §ion.descriptions; settings::view_section(§ion.title) @@ -1425,7 +1420,7 @@ pub fn style() -> Section { .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 { .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 { .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 { #[allow(clippy::too_many_lines)] pub fn window_management() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let descriptions = §ion.descriptions; settings::view_section(§ion.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 { } pub fn experimental() -> Section { + let mut descriptions = Slab::new(); + + let experimental_label = descriptions.insert(fl!("experimental-settings")); + Section::default() - .descriptions(vec![fl!("experimental-settings").into()]) - .view::(|_binder, _page, section| { - let descriptions = &*section.descriptions; + .descriptions(descriptions) + .view::(move |_binder, _page, section| { + let descriptions = §ion.descriptions; let control = row::with_children(vec![ horizontal_space(Length::Fill).into(), @@ -1530,7 +1531,7 @@ pub fn experimental() -> Section { 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 { #[allow(clippy::too_many_lines)] pub fn reset_button() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let descriptions = §ion.descriptions; if page.can_reset { - button::standard(&*descriptions[0]) + button::standard(&descriptions[reset_to_default]) .on_press(Message::Reset) .into() } else { diff --git a/cosmic-settings/src/pages/desktop/dock/applets.rs b/cosmic-settings/src/pages/desktop/dock/applets.rs index 8696452..e047846 100644 --- a/cosmic-settings/src/pages/desktop/dock/applets.rs +++ b/cosmic-settings/src/pages/desktop/dock/applets.rs @@ -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; diff --git a/cosmic-settings/src/pages/desktop/dock/mod.rs b/cosmic-settings/src/pages/desktop/dock/mod.rs index 5833dde..8fc030f 100644 --- a/cosmic-settings/src/pages/desktop/dock/mod.rs +++ b/cosmic-settings/src/pages/desktop/dock/mod.rs @@ -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 { + let mut descriptions = Slab::new(); + + let dock = descriptions.insert(fl!("dock")); + Section::default() - .descriptions(vec![fl!("dock").into()]) - .view::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let descriptions = §ion.descriptions; let Some(container_config) = page.inner.container_config.as_ref() else { return Element::from(text(fl!("unknown"))); }; settings::view_section(§ion.title) .add(settings::flex_item( - &*descriptions[0], + &descriptions[dock], toggler( None, container_config diff --git a/cosmic-settings/src/pages/desktop/options.rs b/cosmic-settings/src/pages/desktop/options.rs index 8d689e3..4ae1181 100644 --- a/cosmic-settings/src/pages/desktop/options.rs +++ b/cosmic-settings/src/pages/desktop/options.rs @@ -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 for Page { } pub fn super_key_action() -> Section { + 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::(|_binder, _page, section| { + .descriptions(descriptions) + .view::(move |_binder, _page, section| { let descriptions = §ion.descriptions; settings::view_section(§ion.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 { } pub fn window_controls() -> Section { + 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::(|binder, _page, section| { + .descriptions(descriptions) + .view::(move |binder, _page, section| { let desktop = binder .page::() .expect("desktop page not found"); @@ -86,7 +91,7 @@ pub fn window_controls() -> Section { settings::view_section(§ion.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 { ), )) .add(settings::flex_item( - &*descriptions[1], + &descriptions[maximize], toggler( None, desktop.cosmic_tk.show_maximize, @@ -109,7 +114,7 @@ pub fn window_controls() -> Section { pub fn panel_dock_links() -> Section { Section::default() .title(fl!("desktop-panels-and-applets")) - .view::(|binder, _page, section| { + .view::(move |binder, _page, section| { // TODO probably a way of getting the entity and its info let mut settings = settings::view_section(§ion.title); settings = if let Some((panel_entity, panel_info)) = diff --git a/cosmic-settings/src/pages/desktop/panel/inner.rs b/cosmic-settings/src/pages/desktop/panel/inner.rs index 32aa55b..83987d2 100644 --- a/cosmic-settings/src/pages/desktop/panel/inner.rs +++ b/cosmic-settings/src/pages/desktop/panel/inner.rs @@ -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 { + 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::

(move |_binder, page, section| { let descriptions = §ion.descriptions; let page = page.inner(); @@ -108,13 +111,13 @@ pub(crate) fn behavior_and_position< }; settings::view_section(§ion.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 { + 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::

(move |_binder, page, section| { let descriptions = §ion.descriptions; let inner = page.inner(); @@ -162,19 +167,19 @@ pub(crate) fn style< }; settings::view_section(§ion.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 + PanelPage>( p: &P, ) -> Section { + 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::

(move |binder, page, section| { let mut settings = settings::view_section(§ion.title); let descriptions = §ion.descriptions; @@ -257,7 +266,7 @@ pub(crate) fn configuration + 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 { + 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::

(move |_binder, _page, section| { let descriptions = §ion.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 { + 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::

(move |_binder, page, section| { let descriptions = §ion.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() } diff --git a/cosmic-settings/src/pages/desktop/wallpaper/mod.rs b/cosmic-settings/src/pages/desktop/wallpaper/mod.rs index a9ceb7c..27e3513 100644 --- a/cosmic-settings/src/pages/desktop/wallpaper/mod.rs +++ b/cosmic-settings/src/pages/desktop/wallpaper/mod.rs @@ -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 { + 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::(|_binder, page, _section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { + let descriptions = §ion.descriptions; let mut children = Vec::with_capacity(3); let mut show_slideshow_toggle = true; @@ -1227,18 +1224,18 @@ pub fn settings() -> Section { 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 { if slideshow_enabled { column .add(settings::flex_item( - &*WALLPAPER_CHANGE, + &descriptions[change_label], dropdown( &page.rotation_options, Some(page.selected_rotation), diff --git a/cosmic-settings/src/pages/desktop/workspaces.rs b/cosmic-settings/src/pages/desktop/workspaces.rs index 5da07a8..5c270a3 100644 --- a/cosmic-settings/src/pages/desktop/workspaces.rs +++ b/cosmic-settings/src/pages/desktop/workspaces.rs @@ -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 { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let descriptions = §ion.descriptions; settings::view_section(§ion.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 { } fn workspace_orientation() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let descriptions = §ion.descriptions; settings::view_section(§ion.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, diff --git a/cosmic-settings/src/pages/display/mod.rs b/cosmic-settings/src/pages/display/mod.rs index 6c9348e..4e32ba1 100644 --- a/cosmic-settings/src/pages/display/mod.rs +++ b/cosmic-settings/src/pages/display/mod.rs @@ -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>, - orientations: [&'static str; 4], + orientations: [String; 4], refresh_rates: Vec, resolutions: Vec, orientation_selected: Option, @@ -170,33 +170,12 @@ impl page::Page for Page { // text::NIGHT_LIGHT_AUTO.as_str().into(), // text::NIGHT_LIGHT_DESCRIPTION.as_str().into(), // ]) - // .view::(|_binder, page, _section| page.night_light_view()), + // .view::(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.list.outputs.len() > 1) - .view::(|_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::(|_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 { - 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 { - let theme = cosmic::theme::active(); - - let Some(&active_id) = self.display_tabs.active_data::() 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 { // column().into() @@ -519,7 +385,7 @@ impl Page { .map(|(key, output)| (&*output.name, key)) .collect::>(); - 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 { + 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.list.outputs.len() > 1) + .view::(move |_binder, page, section| { + let descriptions = §ion.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 { + 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::(move |_binder, page, section| { + let descriptions = §ion.descriptions; + let theme = cosmic::theme::active(); + + let Some(&active_id) = page.display_tabs.active_data::() 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, rates: &[u32]) { *cached_rates = rates .iter() diff --git a/cosmic-settings/src/pages/display/text.rs b/cosmic-settings/src/pages/display/text.rs deleted file mode 100644 index 9daffd2..0000000 --- a/cosmic-settings/src/pages/display/text.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2023 System76 -// 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"); -} diff --git a/cosmic-settings/src/pages/input/keyboard/mod.rs b/cosmic-settings/src/pages/input/keyboard/mod.rs index 5bbb8fd..c9ce9c1 100644 --- a/cosmic-settings/src/pages/input/keyboard/mod.rs +++ b/cosmic-settings/src/pages/input/keyboard/mod.rs @@ -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 for Page { fn input_sources() -> Section { Section::default() .title(fl!("keyboard-sources")) - .view::(|_binder, page, section| { + .view::(move |_binder, page, section| { // TODO Need something more custom, with drag and drop let mut section = settings::view_section(§ion.title); @@ -596,22 +597,24 @@ fn input_sources() -> Section { } fn special_character_entry() -> Section { + 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::(|_binder, _page, section| { + .descriptions(descriptions) + .view::(move |_binder, _page, section| { let descriptions = §ion.descriptions; settings::view_section(§ion.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 { } fn keyboard_shortcuts() -> Section { + 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::(|binder, _page, section| { + .descriptions(descriptions) + .view::(move |binder, _page, section| { let descriptions = §ion.descriptions; let mut section = settings::view_section(§ion.title); @@ -633,7 +640,7 @@ fn keyboard_shortcuts() -> Section { .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 { } fn keyboard_typing_assist() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let descriptions = §ion.descriptions; let theme = cosmic::theme::active(); settings::view_section(§ion.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 { 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 { 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) diff --git a/cosmic-settings/src/pages/input/keyboard/shortcuts.rs b/cosmic-settings/src/pages/input/keyboard/shortcuts.rs index 196cb12..6e0efa9 100644 --- a/cosmic-settings/src/pages/input/keyboard/shortcuts.rs +++ b/cosmic-settings/src/pages/input/keyboard/shortcuts.rs @@ -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 for Page { impl page::AutoBind for Page {} fn shortcuts() -> Section { + let descriptions = Slab::new(); + Section::default() - .descriptions(vec![]) - .view::(|_binder, _page, section| { + .descriptions(descriptions) + .view::(move |_binder, _page, section| { // TODO need something more custom /* settings::view_section(§ion.title) diff --git a/cosmic-settings/src/pages/input/mod.rs b/cosmic-settings/src/pages/input/mod.rs index fd1b532..dcf4bd4 100644 --- a/cosmic-settings/src/pages/input/mod.rs +++ b/cosmic-settings/src/pages/input/mod.rs @@ -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? diff --git a/cosmic-settings/src/pages/input/mouse.rs b/cosmic-settings/src/pages/input/mouse.rs index d3e9a6f..f649cd0 100644 --- a/cosmic-settings/src/pages/input/mouse.rs +++ b/cosmic-settings/src/pages/input/mouse.rs @@ -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 for Page { impl page::AutoBind for Page {} fn mouse() -> Section { + 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::(|binder, _page, section| { + .descriptions(descriptions) + .view::(move |binder, _page, section| { + let descriptions = §ion.descriptions; let input = binder.page::().expect("input page not found"); let theme = cosmic::theme::active(); settings::view_section(§ion.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 { } fn scrolling() -> Section { + 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::(|binder, _page, section| { + .descriptions(descriptions) + .view::(move |binder, _page, section| { + let descriptions = §ion.descriptions; let input = binder.page::().expect("input page not found"); let theme = cosmic::theme::active(); settings::view_section(§ion.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 { .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 diff --git a/cosmic-settings/src/pages/input/touchpad.rs b/cosmic-settings/src/pages/input/touchpad.rs index 0936a90..c3e7dce 100644 --- a/cosmic-settings/src/pages/input/touchpad.rs +++ b/cosmic-settings/src/pages/input/touchpad.rs @@ -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 for Page { impl page::AutoBind for Page {} fn touchpad() -> Section { + 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::(|binder, _page, section| { + .descriptions(descriptions) + .view::(move |binder, _page, section| { + let descriptions = §ion.descriptions; let input = binder.page::().expect("input page not found"); let theme = cosmic::theme::active(); settings::view_section(§ion.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 { ), ) .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 { } fn click_behavior() -> Section { + 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::(|binder, _page, section| { + .descriptions(descriptions) + .view::(move |binder, _page, section| { + let descriptions = §ion.descriptions; let page = binder .page::() .expect("input devices page not found"); @@ -136,7 +123,7 @@ fn click_behavior() -> Section { 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 { .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 { } fn scrolling() -> Section { + 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::(|binder, _page, section| { + .descriptions(descriptions) + .view::(move |binder, _page, section| { + let descriptions = §ion.descriptions; let page = binder .page::() .expect("input devices page not found"); @@ -183,7 +173,7 @@ fn scrolling() -> Section { settings::view_section(§ion.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 { .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 { ) .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 { })) // 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 { } fn swiping() -> Section { + 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::(|_binder, _page, section| { + .descriptions(descriptions) + .view::(move |_binder, _page, section| { + let descriptions = §ion.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) diff --git a/cosmic-settings/src/pages/power/backend/mod.rs b/cosmic-settings/src/pages/power/backend/mod.rs index ba7f63d..ccd41bc 100644 --- a/cosmic-settings/src/pages/power/backend/mod.rs +++ b/cosmic-settings/src/pages/power/backend/mod.rs @@ -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}"), }, } diff --git a/cosmic-settings/src/pages/power/mod.rs b/cosmic-settings/src/pages/power/mod.rs index 7720e46..430c444 100644 --- a/cosmic-settings/src/pages/power/mod.rs +++ b/cosmic-settings/src/pages/power/mod.rs @@ -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 { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, _page, section| { let mut section = settings::view_section(§ion.title); let runtime = tokio::runtime::Runtime::new().unwrap(); diff --git a/cosmic-settings/src/pages/sound.rs b/cosmic-settings/src/pages/sound.rs index c265138..12fc03c 100644 --- a/cosmic-settings/src/pages/sound.rs +++ b/cosmic-settings/src/pages/sound.rs @@ -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 for Page { impl page::AutoBind for Page {} fn alerts() -> Section { + 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::(|_binder, _page, section| { + .descriptions(descriptions) + .view::(move |_binder, _page, section| { settings::view_section(§ion.title) - .add(settings::item(&*section.descriptions[0], text("TODO"))) - .add(settings::item(&*section.descriptions[1], text("TODO"))) + .add(settings::item(§ion.descriptions[volume], text("TODO"))) + .add(settings::item(§ion.descriptions[sound], text("TODO"))) .into() }) } fn applications() -> Section { + 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::(|_binder, _page, section| { + .descriptions(descriptions) + .view::(move |_binder, _page, section| { settings::view_section(§ion.title) - .add(settings::item(&*section.descriptions[0], text("TODO"))) + .add(settings::item( + &*section.descriptions[applications], + text("TODO"), + )) .into() }) } fn input() -> Section { + 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::(|_binder, _page, section| { + .descriptions(descriptions) + .view::(move |_binder, _page, section| { settings::view_section(§ion.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 { + 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::(|_binder, _page, section| { + .descriptions(descriptions) + .view::(move |_binder, _page, section| { settings::view_section(§ion.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() }) } diff --git a/cosmic-settings/src/pages/system/about.rs b/cosmic-settings/src/pages/system/about.rs index 906ac96..fa8d73e 100644 --- a/cosmic-settings/src/pages/system/about.rs +++ b/cosmic-settings/src/pages/system/about.rs @@ -1,12 +1,12 @@ // Copyright 2023 System76 // 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 { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let desc = §ion.descriptions; let hostname_input = editable_input( @@ -122,8 +124,8 @@ fn device() -> Section { .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 { } fn hardware() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let desc = §ion.descriptions; let mut sections = settings::view_section(§ion.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 { } fn os() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { let desc = §ion.descriptions; settings::view_section(§ion.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 { // Section::default() // .title(fl!("about-related")) // .descriptions(vec![fl!("about-related", "support").into()]) -// .view::(|_binder, _page, section| { +// .view::(move |_binder, _page, section| { // settings::view_section(§ion.title) // .add(settings::item(&*section.descriptions[0], text("TODO"))) // .into() diff --git a/cosmic-settings/src/pages/time/date.rs b/cosmic-settings/src/pages/time/date.rs index 762b273..42599ba 100644 --- a/cosmic-settings/src/pages/time/date.rs +++ b/cosmic-settings/src/pages/time/date.rs @@ -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, } impl Default for Page { @@ -115,20 +110,22 @@ pub enum Message { impl page::AutoBind for Page {} fn date() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { settings::view_section(§ion.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 { } fn format() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { settings::view_section(§ion.title) // 24-hour toggle .add( - settings::item::builder(&*TIME_FORMAT_TWENTY_FOUR) + settings::item::builder(§ion.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(§ion.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 { ) // Date on top panel toggle .add( - settings::item::builder(&*TIME_FORMAT_SHOW_DATE) + settings::item::builder(§ion.descriptions[show_date]) .toggler(page.show_date_in_top_panel, Message::ShowDate), ) .apply(cosmic::Element::from) @@ -182,24 +181,26 @@ fn format() -> Section { } fn timezone() -> Section { + 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::(|_binder, page, section| { + .descriptions(descriptions) + .view::(move |_binder, page, section| { settings::view_section(§ion.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) diff --git a/cosmic-settings/src/widget/mod.rs b/cosmic-settings/src/widget/mod.rs index 482d15e..5921665 100644 --- a/cosmic-settings/src/widget/mod.rs +++ b/cosmic-settings/src/widget/mod.rs @@ -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; diff --git a/page/Cargo.toml b/page/Cargo.toml index da4f2fc..fe43070 100644 --- a/page/Cargo.toml +++ b/page/Cargo.toml @@ -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" \ No newline at end of file +url = "2.5.0" +slab = "0.4.9" diff --git a/page/src/section.rs b/page/src/section.rs index 335eb84..03aae2e 100644 --- a/page/src/section.rs +++ b/page/src/section.rs @@ -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 { #[setters(into)] pub title: String, #[setters(into)] - pub descriptions: Vec>, + pub descriptions: Slab, #[setters(skip)] pub show_while: Option>, #[setters(skip)] @@ -44,7 +44,7 @@ impl Default for Section { 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 Section { return true; } - for description in &*self.descriptions { + for (_, description) in &self.descriptions { if rule.is_match(description) { return true; }