feat: refactor the settings page architecture
This commit is contained in:
parent
efdd934e62
commit
c015ad9948
55 changed files with 2212 additions and 1635 deletions
26
app/src/pages/desktop/appearance.rs
Normal file
26
app/src/pages/desktop/appearance.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use slotmap::SlotMap;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Page;
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn content(
|
||||
&self,
|
||||
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
|
||||
) -> Option<page::Content> {
|
||||
Some(vec![sections.insert(Section::default())])
|
||||
}
|
||||
|
||||
fn info(&self) -> page::Info {
|
||||
page::Info::new("appearance", "preferences-pop-desktop-appearance-symbolic")
|
||||
.title(fl!("appearance"))
|
||||
.description(fl!("appearance", "desc"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
26
app/src/pages/desktop/dock.rs
Normal file
26
app/src/pages/desktop/dock.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use slotmap::SlotMap;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Page;
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn content(
|
||||
&self,
|
||||
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
|
||||
) -> Option<page::Content> {
|
||||
Some(vec![sections.insert(Section::default())])
|
||||
}
|
||||
|
||||
fn info(&self) -> page::Info {
|
||||
page::Info::new("dock", "preferences-pop-desktop-dock-symbolic")
|
||||
.title(fl!("dock"))
|
||||
.description(fl!("dock", "desc"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
113
app/src/pages/desktop/mod.rs
Normal file
113
app/src/pages/desktop/mod.rs
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
pub mod appearance;
|
||||
pub mod dock;
|
||||
pub mod notifications;
|
||||
pub mod options;
|
||||
pub mod wallpaper;
|
||||
pub mod workspaces;
|
||||
|
||||
use cosmic_settings_page as page;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct Page {
|
||||
pub top_left_hot_corner: bool,
|
||||
pub show_workspaces_button: bool,
|
||||
pub show_applications_button: bool,
|
||||
pub show_minimize_button: bool,
|
||||
pub show_maximize_button: bool,
|
||||
pub slideshow: bool,
|
||||
pub same_background: bool,
|
||||
}
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn info(&self) -> page::Info {
|
||||
page::Info::new("desktop", "video-display-symbolic").title(fl!("desktop"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {
|
||||
fn sub_pages(page: page::Insert<crate::pages::Message>) -> page::Insert<crate::pages::Message> {
|
||||
page.sub_page::<options::Page>()
|
||||
.sub_page::<wallpaper::Page>()
|
||||
.sub_page::<appearance::Page>()
|
||||
.sub_page::<dock::Page>()
|
||||
.sub_page::<workspaces::Page>()
|
||||
.sub_page::<notifications::Page>()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Message {
|
||||
Slideshow(bool),
|
||||
SameBackground(bool),
|
||||
ShowWorkspacesButton(bool),
|
||||
ShowApplicationsButton(bool),
|
||||
ShowMinimizeButton(bool),
|
||||
ShowMaximizeButton(bool),
|
||||
TopLeftHotCorner(bool),
|
||||
}
|
||||
|
||||
impl Page {
|
||||
pub fn update(&mut self, message: Message) {
|
||||
match message {
|
||||
Message::SameBackground(value) => self.same_background = value,
|
||||
Message::ShowApplicationsButton(value) => self.show_applications_button = value,
|
||||
Message::ShowMaximizeButton(value) => self.show_maximize_button = value,
|
||||
Message::ShowMinimizeButton(value) => self.show_minimize_button = value,
|
||||
Message::ShowWorkspacesButton(value) => self.show_workspaces_button = value,
|
||||
Message::Slideshow(value) => self.slideshow = value,
|
||||
Message::TopLeftHotCorner(value) => self.top_left_hot_corner = value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl From<page::Info> for Message {
|
||||
// fn from(page: page::Info) -> Message {
|
||||
// Message::page::Info(page)
|
||||
// }
|
||||
// }
|
||||
|
||||
// pub enum Output {
|
||||
// page::Info(page::Info),
|
||||
// }
|
||||
|
||||
// impl Subpage::Info for Desktoppage::Info {
|
||||
// //TODO: translate
|
||||
// fn title(&self) -> &'static str {
|
||||
// use Desktoppage::Info::*;
|
||||
// match self {
|
||||
// Workspaces => "Workspaces",
|
||||
// Notifications => "Notifications",
|
||||
// }
|
||||
// }
|
||||
|
||||
// //TODO: translate
|
||||
// fn description(&self) -> &'static str {
|
||||
// use Desktoppage::Info::*;
|
||||
// match self {
|
||||
// Workspaces => "Set workspace number, behavior, and placement.",
|
||||
// Notifications => {
|
||||
// "Do Not Disturb, lockscreen notifications, and per-application settings."
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn icon_name(&self) -> &'static str {
|
||||
// use Desktoppage::Info::*;
|
||||
// match self {
|
||||
// Workspaces => "preferences-pop-desktop-workspaces-symbolic",
|
||||
// Notifications => "preferences-system-notifications-symbolic",
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn parent_page(&self) -> page::Info {
|
||||
// page::Info::Desktop(None)
|
||||
// }
|
||||
|
||||
// fn into_page(self) -> page::Info {
|
||||
// page::Info::Desktop(Some(self))
|
||||
// }
|
||||
// }
|
||||
26
app/src/pages/desktop/notifications.rs
Normal file
26
app/src/pages/desktop/notifications.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use slotmap::SlotMap;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Page;
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn content(
|
||||
&self,
|
||||
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
|
||||
) -> Option<page::Content> {
|
||||
Some(vec![sections.insert(Section::default())])
|
||||
}
|
||||
|
||||
fn info(&self) -> page::Info {
|
||||
page::Info::new("notifications", "preferences-system-notifications-symbolic")
|
||||
.title(fl!("notifications"))
|
||||
.description(fl!("notifications", "desc"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
161
app/src/pages/desktop/options.rs
Normal file
161
app/src/pages/desktop/options.rs
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use super::Message;
|
||||
use apply::Apply;
|
||||
use cosmic::{
|
||||
iced::widget::horizontal_space,
|
||||
iced::Length,
|
||||
widget::{settings, toggler},
|
||||
Element,
|
||||
};
|
||||
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use slotmap::SlotMap;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Page;
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn content(
|
||||
&self,
|
||||
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
|
||||
) -> Option<page::Content> {
|
||||
Some(vec![
|
||||
sections.insert(super_key_action()),
|
||||
sections.insert(hot_corner()),
|
||||
sections.insert(top_panel()),
|
||||
sections.insert(window_controls()),
|
||||
])
|
||||
}
|
||||
|
||||
fn info(&self) -> page::Info {
|
||||
page::Info::new("desktop-options", "video-display-symbolic")
|
||||
.title(fl!("desktop-options"))
|
||||
.description(fl!("desktop-options", "desc"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
|
||||
pub fn hot_corner() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.title(fl!("hot-corner"))
|
||||
.descriptions(vec![fl!("hot-corner", "top-left-corner")])
|
||||
.view::<Page>(|binder, _page, section| {
|
||||
let desktop = binder
|
||||
.page::<super::Page>()
|
||||
.expect("desktop page not found");
|
||||
|
||||
let descriptions = §ion.descriptions;
|
||||
settings::view_section(§ion.title)
|
||||
.add(settings::item(
|
||||
&descriptions[0],
|
||||
toggler(None, desktop.top_left_hot_corner, |value| {
|
||||
Message::TopLeftHotCorner(value)
|
||||
}),
|
||||
))
|
||||
.apply(Element::from)
|
||||
.map(crate::pages::Message::Desktop)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn super_key_action() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.title(fl!("super-key-action"))
|
||||
.descriptions(vec![
|
||||
fl!("super-key-action", "launcher"),
|
||||
fl!("super-key-action", "workspaces"),
|
||||
fl!("super-key-action", "applications"),
|
||||
])
|
||||
.view::<Page>(|_binder, _page, section| {
|
||||
let descriptions = §ion.descriptions;
|
||||
|
||||
settings::view_section(§ion.title)
|
||||
.add(settings::item(
|
||||
&descriptions[0],
|
||||
horizontal_space(Length::Fill),
|
||||
))
|
||||
.add(settings::item(
|
||||
&descriptions[1],
|
||||
horizontal_space(Length::Fill),
|
||||
))
|
||||
.add(settings::item(
|
||||
&descriptions[2],
|
||||
horizontal_space(Length::Fill),
|
||||
))
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn top_panel() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.title(fl!("top-panel"))
|
||||
.descriptions(vec![
|
||||
fl!("top-panel", "workspaces"),
|
||||
fl!("top-panel", "applications"),
|
||||
])
|
||||
.view::<Page>(|binder, _page, section| {
|
||||
let desktop = binder
|
||||
.page::<super::Page>()
|
||||
.expect("desktop page not found");
|
||||
let descriptions = §ion.descriptions;
|
||||
|
||||
settings::view_section(§ion.title)
|
||||
.add(settings::item(
|
||||
&descriptions[0],
|
||||
toggler(
|
||||
None,
|
||||
desktop.show_workspaces_button,
|
||||
Message::ShowWorkspacesButton,
|
||||
),
|
||||
))
|
||||
.add(settings::item(
|
||||
&descriptions[1],
|
||||
toggler(
|
||||
None,
|
||||
desktop.show_applications_button,
|
||||
Message::ShowApplicationsButton,
|
||||
),
|
||||
))
|
||||
.apply(Element::from)
|
||||
.map(crate::pages::Message::Desktop)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn window_controls() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.title(fl!("window-controls"))
|
||||
.descriptions(vec![
|
||||
fl!("window-controls", "minimize"),
|
||||
fl!("window-controls", "maximize"),
|
||||
])
|
||||
.view::<Page>(|binder, _page, section| {
|
||||
let desktop = binder
|
||||
.page::<super::Page>()
|
||||
.expect("desktop page not found");
|
||||
let descriptions = §ion.descriptions;
|
||||
|
||||
settings::view_section(§ion.title)
|
||||
.add(settings::item(
|
||||
&descriptions[0],
|
||||
toggler(
|
||||
None,
|
||||
desktop.show_minimize_button,
|
||||
Message::ShowMinimizeButton,
|
||||
),
|
||||
))
|
||||
.add(settings::item(
|
||||
&descriptions[1],
|
||||
toggler(
|
||||
None,
|
||||
desktop.show_maximize_button,
|
||||
Message::ShowMaximizeButton,
|
||||
),
|
||||
))
|
||||
.apply(Element::from)
|
||||
.map(crate::pages::Message::Desktop)
|
||||
})
|
||||
}
|
||||
98
app/src/pages/desktop/wallpaper.rs
Normal file
98
app/src/pages/desktop/wallpaper.rs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use super::Message;
|
||||
use apply::Apply;
|
||||
use cosmic::{
|
||||
iced::widget::{column, container, horizontal_space, image, row, svg, text},
|
||||
iced::Length,
|
||||
theme,
|
||||
widget::{list_column, settings, toggler},
|
||||
Element,
|
||||
};
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use slotmap::SlotMap;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Page;
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn content(
|
||||
&self,
|
||||
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
|
||||
) -> Option<page::Content> {
|
||||
Some(vec![sections.insert(settings())])
|
||||
}
|
||||
|
||||
fn info(&self) -> page::Info {
|
||||
page::Info::new("wallpaper", "preferences-desktop-wallpaper-symbolic")
|
||||
.title(fl!("wallpaper"))
|
||||
.description(fl!("wallpaper", "desc"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
|
||||
pub fn settings() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.descriptions(vec![
|
||||
fl!("wallpaper", "same"),
|
||||
fl!("wallpaper", "fit"),
|
||||
fl!("wallpaper", "slide"),
|
||||
fl!("wallpaper", "change"),
|
||||
])
|
||||
.view::<Page>(|binder, _page, section| {
|
||||
let desktop = binder
|
||||
.page::<super::Page>()
|
||||
.expect("desktop page not found");
|
||||
let descriptions = §ion.descriptions;
|
||||
let image_paths: Vec<std::path::PathBuf> = Vec::new();
|
||||
|
||||
let mut image_column = Vec::with_capacity(image_paths.len() / 4);
|
||||
for chunk in image_paths.chunks(4) {
|
||||
let mut image_row = Vec::with_capacity(chunk.len());
|
||||
for image_path in chunk.iter() {
|
||||
image_row.push(if image_path.ends_with(".svg") {
|
||||
svg(svg::Handle::from_path(image_path))
|
||||
.width(Length::Units(150))
|
||||
.into()
|
||||
} else {
|
||||
image(image_path).width(Length::Units(150)).into()
|
||||
});
|
||||
}
|
||||
image_column.push(row(image_row).spacing(16).into());
|
||||
}
|
||||
|
||||
let children = vec![
|
||||
row!(
|
||||
horizontal_space(Length::Fill),
|
||||
container(
|
||||
image("/usr/share/backgrounds/pop/kate-hazen-COSMIC-desktop-wallpaper.png")
|
||||
.width(Length::Units(300))
|
||||
)
|
||||
.padding(4)
|
||||
.style(theme::Container::Box),
|
||||
horizontal_space(Length::Fill),
|
||||
)
|
||||
.into(),
|
||||
list_column()
|
||||
.add(settings::item(
|
||||
&descriptions[0],
|
||||
toggler(None, desktop.same_background, Message::SameBackground),
|
||||
))
|
||||
.add(settings::item(&descriptions[1], text("TODO")))
|
||||
.add(settings::item(
|
||||
&descriptions[2],
|
||||
toggler(None, desktop.slideshow, Message::Slideshow),
|
||||
))
|
||||
.into(),
|
||||
column(image_column).spacing(16).into(),
|
||||
];
|
||||
|
||||
settings::view_column(children)
|
||||
.padding(0)
|
||||
.apply(Element::from)
|
||||
.map(crate::pages::Message::Desktop)
|
||||
})
|
||||
}
|
||||
76
app/src/pages/desktop/workspaces.rs
Normal file
76
app/src/pages/desktop/workspaces.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use cosmic::iced::{widget::horizontal_space, Length};
|
||||
use cosmic::widget::settings;
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use slotmap::SlotMap;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Page;
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn content(
|
||||
&self,
|
||||
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
|
||||
) -> Option<page::Content> {
|
||||
Some(vec![
|
||||
sections.insert(behavior()),
|
||||
sections.insert(multi_behavior()),
|
||||
])
|
||||
}
|
||||
|
||||
fn info(&self) -> page::Info {
|
||||
page::Info::new("workspaces", "preferences-pop-desktop-workspaces-symbolic")
|
||||
.title(fl!("workspaces"))
|
||||
.description(fl!("workspaces", "desc"))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
|
||||
fn behavior() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.title(fl!("workspaces-behavior"))
|
||||
.descriptions(vec![
|
||||
fl!("workspaces-behavior", "dynamic"),
|
||||
fl!("workspaces-behavior", "fixed"),
|
||||
])
|
||||
.view::<Page>(|_binder, _page, section| {
|
||||
let descriptions = §ion.descriptions;
|
||||
|
||||
settings::view_section(§ion.title)
|
||||
.add(settings::item(
|
||||
&descriptions[0],
|
||||
horizontal_space(Length::Fill),
|
||||
))
|
||||
.add(settings::item(
|
||||
&descriptions[1],
|
||||
horizontal_space(Length::Fill),
|
||||
))
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
fn multi_behavior() -> Section<crate::pages::Message> {
|
||||
Section::default()
|
||||
.title(fl!("workspaces-multi-behavior"))
|
||||
.descriptions(vec![
|
||||
fl!("workspaces-multi-behavior", "span"),
|
||||
fl!("workspaces-multi-behavior", "separate"),
|
||||
])
|
||||
.view::<Page>(|_binder, _page, section| {
|
||||
let descriptions = §ion.descriptions;
|
||||
settings::view_section(§ion.title)
|
||||
.add(settings::item(
|
||||
&descriptions[0],
|
||||
horizontal_space(Length::Fill),
|
||||
))
|
||||
.add(settings::item(
|
||||
&descriptions[1],
|
||||
horizontal_space(Length::Fill),
|
||||
))
|
||||
.into()
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue