feat: make ContextDrawer model accessible to pages

This commit is contained in:
Michael Aaron Murphy 2025-04-21 18:14:58 +02:00 • committed by Michael Murphy
parent bb41b4985e
commit 45f1183d92
24 changed files with 210 additions and 223 deletions

View file

@ -78,7 +78,7 @@ zbus = { version = "4.4.0", default-features = false, features = [
"tokio",
], optional = true }
zbus_polkit = { version = "4.0.0", optional = true }
fontdb = "=0.16.2"
fontdb = "0.23.0"
fixed_decimal = "0.5.6"
mime = "0.3.17"
rustix = { version = "1.0.3", features = ["process"] }

View file

@ -146,7 +146,6 @@ impl SettingsApp {
#[derive(Clone, Debug)]
pub enum Message {
CloseContextDrawer,
#[cfg(feature = "wayland")]
DesktopInfo,
Error(String),
@ -370,6 +369,8 @@ impl cosmic::Application for SettingsApp {
}
Message::PageMessage(message) => match message {
crate::pages::Message::CloseContextDrawer => return self.close_context_drawer(),
#[cfg(feature = "page-accessibility")]
crate::pages::Message::Accessibility(message) => {
if let Some(page) = self.pages.page_mut::<accessibility::Page>() {
@ -761,8 +762,6 @@ impl cosmic::Application for SettingsApp {
self.context_title = Some(title.to_string());
}
Message::CloseContextDrawer => return self.close_context_drawer(),
Message::Error(error) => {
tracing::error!(error, "error occurred");
}
@ -814,10 +813,9 @@ impl cosmic::Application for SettingsApp {
if self.core.window.show_context {
self.active_context_page.and_then(|context_page| {
self.pages.context_drawer(context_page).map(|cd| {
let cd = cosmic::app::context_drawer::context_drawer(
cd.map(Message::PageMessage),
Message::CloseContextDrawer,
);
let cd = cd.map(Message::from);
// TODO: The page should handle this?
if let Some(title) = self.context_title.as_ref() {
cd.title(title)
} else {

View file

@ -1,3 +1,4 @@
use cosmic::app::ContextDrawer;
use cosmic::iced::{Alignment, Length};
use cosmic::widget::{button, icon, settings, text};
use cosmic::{Apply, Element, Task, widget};
@ -43,14 +44,13 @@ impl Default for Page {
#[derive(Clone, Debug)]
pub enum Message {
ShowApplicationSidebar(DirectoryType),
UpdateStartupApplications(CachedApps),
UpdateApplications(CachedApps),
ApplicationSearch(String),
AddStartupApplication(DirectoryType, DesktopEntry),
RemoveStartupApplication(DirectoryType, DesktopEntry, bool),
ApplicationSearch(String),
CancelRemoveStartupApplication,
RemoveStartupApplication(DirectoryType, DesktopEntry, bool),
ShowApplicationSidebar(DirectoryType),
UpdateApplications(CachedApps),
UpdateStartupApplications(CachedApps),
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
@ -110,11 +110,13 @@ impl page::Page<crate::pages::Message> for Page {
Some(vec![sections.insert(apps())])
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
fn context_drawer(&self) -> Option<ContextDrawer<crate::pages::Message>> {
match &self.context {
Some(Context::AddApplication(directory_type)) => {
Some(self.add_application_context_view(directory_type.clone()))
}
Some(Context::AddApplication(directory_type)) => Some(cosmic::app::context_drawer(
self.add_application_context_view(directory_type.clone())
.map(crate::pages::Message::from),
crate::pages::Message::CloseContextDrawer,
)),
None => None,
}
}

View file

@ -7,6 +7,7 @@ pub mod icon_themes;
use std::borrow::Cow;
use std::sync::Arc;
use cosmic::app::ContextDrawer;
//TODO: use embedded cosmic-files for portability
use cosmic::config::CosmicTk;
use cosmic::cosmic_config::{Config, ConfigSet, CosmicConfigEntry};
@ -1342,7 +1343,7 @@ impl Page {
let task = match message {
ColorPickerUpdate::AppliedColor | ColorPickerUpdate::Reset => {
needs_update = true;
cosmic::task::message(crate::app::Message::CloseContextDrawer)
cosmic::task::message(crate::pages::Message::CloseContextDrawer)
}
ColorPickerUpdate::ActionFinished => {
@ -1351,7 +1352,7 @@ impl Page {
}
ColorPickerUpdate::Cancel => {
cosmic::task::message(crate::app::Message::CloseContextDrawer)
cosmic::task::message(crate::pages::Message::CloseContextDrawer)
}
ColorPickerUpdate::ToggleColorPicker => {
@ -1621,7 +1622,7 @@ impl page::Page<crate::pages::Message> for Page {
cosmic::task::message(crate::pages::Message::Appearance(Message::Left))
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
let view = match self.context_view? {
ContextView::AccentWindowHint => color_picker_context_view(
None,
@ -1710,7 +1711,10 @@ impl page::Page<crate::pages::Message> for Page {
ContextView::IconsAndToolkit => self.icons_and_toolkit(),
};
Some(view)
Some(cosmic::app::context_drawer(
view,
crate::pages::Message::CloseContextDrawer,
))
}
}

View file

@ -1,5 +1,6 @@
use cosmic::{
Apply, Element, Task,
app::ContextDrawer,
cosmic_config::CosmicConfigEntry,
iced::{Alignment, Length},
widget::{button, container, row},
@ -13,7 +14,7 @@ use crate::{
app,
pages::{
self,
desktop::panel::applets_inner::{self, AppletsPage, ContextDrawer, lists},
desktop::panel::applets_inner::{self, AppletsPage, ContextDrawerVariant, lists},
},
};
@ -98,14 +99,17 @@ impl page::Page<crate::pages::Message> for Page {
Some(content)
}
fn context_drawer(&self) -> Option<Element<crate::pages::Message>> {
Some(match self.inner.context {
Some(ContextDrawer::AddApplet) => self
.inner
.add_applet_view(|msg| crate::pages::Message::DockApplet(Message(msg))),
fn context_drawer(&self) -> Option<ContextDrawer<crate::pages::Message>> {
Some(cosmic::app::context_drawer(
match self.inner.context {
Some(ContextDrawerVariant::AddApplet) => self
.inner
.add_applet_view(|msg| crate::pages::Message::DockApplet(Message(msg))),
None => return None,
})
None => return None,
},
crate::pages::Message::CloseContextDrawer,
))
}
fn set_id(&mut self, entity: cosmic_settings_page::Entity) {

View file

@ -1,3 +1,4 @@
use cosmic::app::ContextDrawer;
use cosmic::iced::Vector;
use cosmic::iced::clipboard::dnd::{
DndAction, DndDestinationRectangle, DndEvent, OfferEvent, SourceEvent,
@ -56,7 +57,7 @@ pub struct Page {
pub(crate) current_config: Option<CosmicPanelConfig>,
pub(crate) reorder_widget_state: Option<(Applet<'static>, CosmicPanelConfig)>,
pub(crate) search: String,
pub(crate) context: Option<ContextDrawer>,
pub(crate) context: Option<ContextDrawerVariant>,
}
impl Default for Page {
@ -132,14 +133,17 @@ impl page::Page<crate::pages::Message> for Page {
Some(content)
}
fn context_drawer(&self) -> Option<Element<pages::Message>> {
Some(match self.context {
Some(ContextDrawer::AddApplet) => {
self.add_applet_view(crate::pages::Message::PanelApplet)
}
fn context_drawer(&self) -> Option<ContextDrawer<pages::Message>> {
Some(cosmic::app::context_drawer(
match self.context {
Some(ContextDrawerVariant::AddApplet) => {
self.add_applet_view(crate::pages::Message::PanelApplet)
}
None => return None,
})
None => return None,
},
crate::pages::Message::CloseContextDrawer,
))
}
fn on_enter(&mut self) -> Task<crate::pages::Message> {
@ -196,7 +200,7 @@ impl Debug for Message {
}
}
pub enum ContextDrawer {
pub enum ContextDrawerVariant {
AddApplet,
}
@ -416,7 +420,7 @@ impl Page {
self.save();
}
Message::AddAppletDrawer => {
self.context = Some(ContextDrawer::AddApplet);
self.context = Some(ContextDrawerVariant::AddApplet);
return cosmic::task::message(app::Message::OpenContextDrawer(
self.entity,
Cow::Owned(fl!("add-applet")),

View file

@ -16,7 +16,6 @@ use std::{
#[cfg(feature = "xdg-portal")]
use cosmic::dialog::file_chooser;
use cosmic::iced_runtime::core::image::Handle as ImageHandle;
use cosmic::widget::{
button, dropdown, list_column, row,
segmented_button::{self, SingleSelectModel},
@ -26,6 +25,7 @@ use cosmic::{
Apply, Element, Task,
widget::{ColorPickerModel, color_picker::ColorPickerUpdate, icon},
};
use cosmic::{app::ContextDrawer, iced_runtime::core::image::Handle as ImageHandle};
use cosmic::{
iced::{Alignment, Color, Length, window},
surface,
@ -276,15 +276,20 @@ impl page::Page<crate::pages::Message> for Page {
Task::none()
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
self.context_view.map(|view| match view {
ContextView::AddColor => crate::widget::color_picker_context_view(
None,
fl!("reset-to-default").into(),
Message::ColorAdd,
&self.color_model,
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
self.context_view.map(|view| {
cosmic::app::context_drawer(
match view {
ContextView::AddColor => crate::widget::color_picker_context_view(
None,
fl!("reset-to-default").into(),
Message::ColorAdd,
&self.color_model,
)
.map(crate::pages::Message::DesktopWallpaper),
},
crate::pages::Message::CloseContextDrawer,
)
.map(crate::pages::Message::DesktopWallpaper),
})
}
}

View file

@ -7,6 +7,7 @@ use std::cmp;
use cosmic::{
Apply, Element, Task,
app::ContextDrawer,
cosmic_config::{self, ConfigSet},
iced::{Alignment, Color, Length},
iced_core::Border,
@ -296,20 +297,21 @@ impl page::Page<crate::pages::Message> for Page {
.description(fl!("keyboard", "desc"))
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
match self.context {
Some(Context::ShowInputSourcesContext) => Some(self.add_input_source_view()),
Some(Context::SpecialCharacter(special_key)) => self
.special_character_key_view(special_key)
.map(crate::pages::Message::Keyboard)
.apply(Some),
Some(Context::NumlockState) => self
.numlock_state_view()
.map(crate::pages::Message::Keyboard)
.apply(Some),
None => None,
}
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
self.context.as_ref().map(|context| {
cosmic::app::context_drawer(
match context {
Context::ShowInputSourcesContext => self.add_input_source_view(),
Context::SpecialCharacter(special_key) => self
.special_character_key_view(*special_key)
.map(crate::pages::Message::Keyboard),
Context::NumlockState => self
.numlock_state_view()
.map(crate::pages::Message::Keyboard),
},
crate::pages::Message::CloseContextDrawer,
)
})
}
fn on_enter(&mut self) -> Task<crate::pages::Message> {

View file

@ -1,6 +1,7 @@
// Copyright 2024 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic::app::ContextDrawer;
use cosmic::iced::{Alignment, Length};
use cosmic::widget::{self, button, icon, settings, text};
use cosmic::{Apply, Element, Task, theme};
@ -168,15 +169,22 @@ impl Model {
self.shortcuts_config_set(shortcuts);
}
pub(super) fn context_drawer(&self) -> Option<Element<'_, ShortcutMessage>> {
pub(super) fn context_drawer(
&self,
apply: fn(ShortcutMessage) -> crate::pages::Message,
) -> Option<ContextDrawer<'_, crate::pages::Message>> {
self.shortcut_context.as_ref().map(|id| {
context_drawer(
&self.shortcut_title,
&self.shortcut_models,
self.editing,
self.add_keybindings_button_id.clone(),
*id,
self.custom,
cosmic::app::context_drawer(
context_drawer(
&self.shortcut_title,
&self.shortcut_models,
self.editing,
self.add_keybindings_button_id.clone(),
*id,
self.custom,
)
.map(apply),
crate::pages::Message::CloseContextDrawer,
)
})
}

View file

@ -5,6 +5,7 @@ use std::str::FromStr;
use super::{ShortcutBinding, ShortcutMessage, ShortcutModel};
use cosmic::app::ContextDrawer;
use cosmic::iced::{Alignment, Length};
use cosmic::widget::{self, button, icon};
use cosmic::{Apply, Element, Task};
@ -360,15 +361,18 @@ impl page::Page<crate::pages::Message> for Page {
.map(|el| el.map(|m| crate::pages::Message::CustomShortcuts(Message::Shortcut(m))))
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
if self.add_shortcut.active {
Some(self.add_keybinding_context())
Some(cosmic::app::context_drawer(
self.add_keybinding_context()
.map(crate::pages::Message::CustomShortcuts),
crate::pages::Message::CloseContextDrawer,
))
} else {
self.model
.context_drawer()
.map(|el| el.map(Message::Shortcut))
self.model.context_drawer(|msg| {
crate::pages::Message::CustomShortcuts(Message::Shortcut(msg))
})
}
.map(|el| el.map(crate::pages::Message::CustomShortcuts))
}
fn on_context_drawer_close(&mut self) -> Task<crate::pages::Message> {

View file

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-only
use super::{ShortcutMessage, ShortcutModel};
use cosmic::{Element, Task};
use cosmic::{Element, Task, app::ContextDrawer};
use cosmic_settings_config::shortcuts::Action;
use cosmic_settings_config::shortcuts::action::ResizeDirection;
use cosmic_settings_page::{self as page, Section, section};
@ -47,10 +47,9 @@ impl page::Page<crate::pages::Message> for Page {
Some(vec![sections.insert(shortcuts())])
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
self.model
.context_drawer()
.map(|el| el.map(crate::pages::Message::ManageWindowShortcuts))
.context_drawer(crate::pages::Message::ManageWindowShortcuts)
}
fn dialog(&self) -> Option<Element<'_, crate::pages::Message>> {

View file

@ -12,6 +12,7 @@ pub mod nav;
pub mod system;
pub mod tiling;
use cosmic::app::ContextDrawer;
use cosmic::iced::Length;
use cosmic::widget::{self, icon, settings, text};
use cosmic::{Apply, Element, Task, theme};
@ -122,12 +123,12 @@ impl page::Page<crate::pages::Message> for Page {
.description(fl!("keyboard-shortcuts", "desc"))
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
if self.search_model.shortcut_models.is_empty() {
None
} else {
self.search_model.context_drawer().map(|el| {
el.map(|msg| crate::pages::Message::KeyboardShortcuts(Message::SearchShortcut(msg)))
self.search_model.context_drawer(|msg| {
crate::pages::Message::KeyboardShortcuts(Message::SearchShortcut(msg))
})
}
}

View file

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-only
//
use super::{ShortcutMessage, ShortcutModel};
use cosmic::{Element, Task};
use cosmic::{Element, Task, app::ContextDrawer};
use cosmic_settings_config::shortcuts::Action;
use cosmic_settings_config::shortcuts::action::Direction;
use cosmic_settings_page::{self as page, Section, section};
@ -47,10 +47,9 @@ impl page::Page<crate::pages::Message> for Page {
Some(vec![sections.insert(shortcuts())])
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
self.model
.context_drawer()
.map(|el| el.map(crate::pages::Message::MoveWindowShortcuts))
.context_drawer(crate::pages::Message::MoveWindowShortcuts)
}
fn dialog(&self) -> Option<Element<'_, crate::pages::Message>> {

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-only
use super::{ShortcutMessage, ShortcutModel};
use cosmic::app::ContextDrawer;
use cosmic::{Element, Task};
use cosmic_settings_config::shortcuts::Action;
use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection};
@ -47,10 +48,9 @@ impl page::Page<crate::pages::Message> for Page {
Some(vec![sections.insert(shortcuts())])
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
self.model
.context_drawer()
.map(|el| el.map(crate::pages::Message::NavShortcuts))
.context_drawer(crate::pages::Message::NavShortcuts)
}
fn dialog(&self) -> Option<Element<'_, crate::pages::Message>> {

View file

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-only
use super::{ShortcutMessage, ShortcutModel};
use cosmic::{Element, Task};
use cosmic::{Element, Task, app::ContextDrawer};
use cosmic_settings_config::shortcuts::Action;
use cosmic_settings_config::shortcuts::action::System as SystemAction;
use cosmic_settings_page::{self as page, Section, section};
@ -47,10 +47,9 @@ impl page::Page<crate::pages::Message> for Page {
Some(vec![sections.insert(shortcuts())])
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
self.model
.context_drawer()
.map(|el| el.map(crate::pages::Message::SystemShortcuts))
.context_drawer(crate::pages::Message::SystemShortcuts)
}
fn dialog(&self) -> Option<Element<'_, crate::pages::Message>> {

View file

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-only
use super::{ShortcutMessage, ShortcutModel};
use cosmic::{Element, Task};
use cosmic::{Element, Task, app::ContextDrawer};
use cosmic_settings_config::shortcuts::Action;
use cosmic_settings_config::shortcuts::action::Orientation;
use cosmic_settings_page::{self as page, Section, section};
@ -47,10 +47,9 @@ impl page::Page<crate::pages::Message> for Page {
Some(vec![sections.insert(shortcuts())])
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
self.model
.context_drawer()
.map(|el| el.map(crate::pages::Message::TilingShortcuts))
.context_drawer(crate::pages::Message::TilingShortcuts)
}
fn dialog(&self) -> Option<Element<'_, crate::pages::Message>> {

View file

@ -24,6 +24,7 @@ pub mod time;
#[derive(Clone, Debug)]
pub enum Message {
// Page-specific messages
#[cfg(feature = "page-accessibility")]
Accessibility(accessibility::Message),
#[cfg(feature = "page-accessibility")]
@ -96,6 +97,9 @@ pub enum Message {
WindowManagement(desktop::window_management::Message),
#[cfg(feature = "page-networking")]
Wired(networking::wired::Message),
// Common page functionality
CloseContextDrawer,
}
impl From<Message> for crate::Message {

View file

@ -6,6 +6,7 @@ use std::str::FromStr;
use chrono::{Datelike, Timelike};
use cosmic::{
Apply, Element, Task,
app::ContextDrawer,
cosmic_config::{self, ConfigGet, ConfigSet},
iced_core::text::Wrapping,
surface,
@ -165,9 +166,13 @@ impl page::Page<crate::pages::Message> for Page {
.map(crate::pages::Message::DateAndTime)
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
fn context_drawer(&self) -> Option<ContextDrawer<crate::pages::Message>> {
if self.timezone_context {
return Some(self.timezone_context_view());
return Some(cosmic::app::context_drawer(
self.timezone_context_view()
.map(crate::pages::Message::from),
crate::pages::Message::CloseContextDrawer,
));
}
None
@ -259,14 +264,14 @@ impl Page {
Message::Error(why) => {
tracing::error!(why, "failed to set timezone");
self.timezone_context = false;
return cosmic::task::message(crate::Message::CloseContextDrawer);
return cosmic::task::message(crate::pages::Message::CloseContextDrawer);
}
Message::UpdateTime => {
self.set_ntp(true);
self.update_local_time();
self.timezone_context = false;
return cosmic::task::message(crate::Message::CloseContextDrawer);
return cosmic::task::message(crate::pages::Message::CloseContextDrawer);
}
Message::Refresh(info) => {

View file

@ -6,6 +6,7 @@ use std::rc::Rc;
use std::str::FromStr;
use std::sync::Arc;
use cosmic::app::ContextDrawer;
use cosmic::iced::{Alignment, Border, Color, Length};
use cosmic::iced_core::text::Wrapping;
use cosmic::widget::{self, button, container};
@ -152,11 +153,15 @@ impl page::Page<crate::pages::Message> for Page {
cosmic::Task::none()
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
Some(match self.context.as_ref()? {
ContextView::AddLanguage => self.add_language_view(),
ContextView::Region => self.region_view(),
})
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
Some(cosmic::app::context_drawer(
match self.context.as_ref()? {
ContextView::AddLanguage => self.add_language_view(),
ContextView::Region => self.region_view(),
}
.map(crate::pages::Message::from),
crate::pages::Message::CloseContextDrawer,
))
}
}