improv: use ContextDrawer model in pages

This commit is contained in:
Vukašin Vojinović 2025-04-22 01:06:37 +02:00 • committed by Michael Murphy
parent 45f1183d92
commit 5c92c91443
12 changed files with 276 additions and 314 deletions

View file

@ -150,7 +150,7 @@ pub enum Message {
DesktopInfo, DesktopInfo,
Error(String), Error(String),
None, None,
OpenContextDrawer(Entity, Cow<'static, str>), OpenContextDrawer(Entity),
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
OutputAdded(OutputInfo, WlOutput), OutputAdded(OutputInfo, WlOutput),
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
@ -756,10 +756,9 @@ impl cosmic::Application for SettingsApp {
Message::SetTheme(t) => return cosmic::command::set_theme(t), Message::SetTheme(t) => return cosmic::command::set_theme(t),
Message::OpenContextDrawer(page, title) => { Message::OpenContextDrawer(page) => {
self.core.window.show_context = true; self.core.window.show_context = true;
self.active_context_page = Some(page); self.active_context_page = Some(page);
self.context_title = Some(title.to_string());
} }
Message::Error(error) => { Message::Error(error) => {
@ -1124,8 +1123,6 @@ impl SettingsApp {
/// Displays the sub-pages view of a page. /// Displays the sub-pages view of a page.
fn sub_page_view(&self, sub_pages: &[page::Entity]) -> cosmic::Element<Message> { fn sub_page_view(&self, sub_pages: &[page::Entity]) -> cosmic::Element<Message> {
let theme = cosmic::theme::active();
let page_list = sub_pages let page_list = sub_pages
.iter() .iter()
.copied() .copied()
@ -1143,7 +1140,7 @@ impl SettingsApp {
)) ))
}, },
) )
.spacing(theme.cosmic().space_s()) .spacing(cosmic::theme::spacing().space_s)
.apply(|widget| scrollable(self.page_container(widget)).height(Length::Fill)) .apply(|widget| scrollable(self.page_container(widget)).height(Length::Fill))
.apply(Element::from) .apply(Element::from)
.map(Message::Page); .map(Message::Page);

View file

@ -112,11 +112,23 @@ impl page::Page<crate::pages::Message> for Page {
fn context_drawer(&self) -> Option<ContextDrawer<crate::pages::Message>> { fn context_drawer(&self) -> Option<ContextDrawer<crate::pages::Message>> {
match &self.context { match &self.context {
Some(Context::AddApplication(directory_type)) => Some(cosmic::app::context_drawer( Some(Context::AddApplication(directory_type)) => {
self.add_application_context_view(directory_type.clone()) let search = widget::search_input(fl!("type-to-search"), &self.application_search)
.map(crate::pages::Message::from), .on_input(Message::ApplicationSearch)
crate::pages::Message::CloseContextDrawer, .on_clear(Message::ApplicationSearch(String::new()))
)), .apply(Element::from)
.map(crate::pages::Message::from);
Some(
cosmic::app::context_drawer(
self.add_application_context_view(directory_type.clone())
.map(crate::pages::Message::from),
crate::pages::Message::CloseContextDrawer,
)
.title(fl!("startup-apps", "search-for-application"))
.header(search),
)
}
None => None, None => None,
} }
} }
@ -203,10 +215,7 @@ impl Page {
} }
Message::ShowApplicationSidebar(directory_type) => { Message::ShowApplicationSidebar(directory_type) => {
self.context = Some(Context::AddApplication(directory_type)); self.context = Some(Context::AddApplication(directory_type));
return cosmic::task::message(crate::app::Message::OpenContextDrawer( return cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity));
self.entity,
fl!("startup-apps", "search-for-application").into(),
));
} }
Message::AddStartupApplication(directory_type, app) => { Message::AddStartupApplication(directory_type, app) => {
let mut file_name = app.clone().appid; let mut file_name = app.clone().appid;
@ -311,13 +320,7 @@ impl Page {
&self, &self,
directory_type: DirectoryType, directory_type: DirectoryType,
) -> Element<'_, crate::pages::Message> { ) -> Element<'_, crate::pages::Message> {
let cosmic::cosmic_theme::Spacing { let cosmic::cosmic_theme::Spacing { space_xs, .. } = cosmic::theme::spacing();
space_xs, space_l, ..
} = cosmic::theme::spacing();
let search = widget::search_input(fl!("type-to-search"), &self.application_search)
.on_input(Message::ApplicationSearch)
.on_clear(Message::ApplicationSearch(String::new()));
let mut list = widget::list_column(); let mut list = widget::list_column();
let search_input = &self.application_search.trim().to_lowercase(); let search_input = &self.application_search.trim().to_lowercase();
@ -355,12 +358,7 @@ impl Page {
} }
} }
widget::column() list.apply(Element::from)
.padding([2, 0])
.spacing(space_l)
.push(search)
.push(list)
.apply(Element::from)
.map(crate::pages::Message::StartupApps) .map(crate::pages::Message::StartupApps)
} }
} }

View file

@ -8,7 +8,6 @@ use cosmic::{
Apply, Element, Task, Apply, Element, Task,
config::{CosmicTk, FontConfig}, config::{CosmicTk, FontConfig},
iced_core::text::Wrapping, iced_core::text::Wrapping,
theme,
widget::{self, settings, svg}, widget::{self, settings, svg},
}; };
use cosmic_config::ConfigSet; use cosmic_config::ConfigSet;
@ -65,20 +64,13 @@ pub fn load_font_families() -> (Vec<Arc<str>>, Vec<Arc<str>>) {
pub fn selection_context<'a>( pub fn selection_context<'a>(
families: &'a [Arc<str>], families: &'a [Arc<str>],
search: &'a str,
current_font: &str, current_font: &str,
system: bool, system: bool,
) -> Element<'a, super::Message> { ) -> Element<'a, super::Message> {
let space_l = theme::active().cosmic().spacing.space_l;
let svg_accent = Rc::new(|theme: &cosmic::Theme| svg::Style { let svg_accent = Rc::new(|theme: &cosmic::Theme| svg::Style {
color: Some(theme.cosmic().accent_color().into()), color: Some(theme.cosmic().accent_color().into()),
}); });
let search_input = widget::search_input(fl!("type-to-search"), search)
.on_input(super::Message::FontSearch)
.on_clear(super::Message::FontSearch(String::new()));
let list = families.iter().fold(widget::list_column(), |list, family| { let list = families.iter().fold(widget::list_column(), |list, family| {
let selected = &**family == current_font; let selected = &**family == current_font;
list.add( list.add(
@ -105,12 +97,7 @@ pub fn selection_context<'a>(
) )
}); });
widget::column() list.into()
.padding([2, 0])
.spacing(space_l)
.push(search_input)
.push(list)
.into()
} }
/// Set the preferred icon theme for GNOME/GTK applications. /// Set the preferred icon theme for GNOME/GTK applications.

View file

@ -7,7 +7,7 @@ pub mod icon_themes;
use std::borrow::Cow; use std::borrow::Cow;
use std::sync::Arc; use std::sync::Arc;
use cosmic::app::ContextDrawer; use cosmic::app::{ContextDrawer, context_drawer};
//TODO: use embedded cosmic-files for portability //TODO: use embedded cosmic-files for portability
use cosmic::config::CosmicTk; use cosmic::config::CosmicTk;
use cosmic::cosmic_config::{Config, ConfigSet, CosmicConfigEntry}; use cosmic::cosmic_config::{Config, ConfigSet, CosmicConfigEntry};
@ -19,7 +19,6 @@ use cosmic::cosmic_theme::{
#[cfg(feature = "xdg-portal")] #[cfg(feature = "xdg-portal")]
use cosmic::dialog::file_chooser::{self, FileFilter}; use cosmic::dialog::file_chooser::{self, FileFilter};
use cosmic::iced_core::{Alignment, Color, Length}; use cosmic::iced_core::{Alignment, Color, Length};
use cosmic::iced_widget::scrollable::{Direction, Scrollbar};
use cosmic::widget::icon::{from_name, icon}; use cosmic::widget::icon::{from_name, icon};
use cosmic::widget::{ use cosmic::widget::{
ColorPickerModel, button, color_picker::ColorPickerUpdate, container, flex_row, ColorPickerModel, button, color_picker::ColorPickerUpdate, container, flex_row,
@ -469,9 +468,14 @@ impl From<CornerRadii> for Roundness {
impl Page { impl Page {
fn icons_and_toolkit(&self) -> Element<'_, crate::pages::Message> { fn icons_and_toolkit(&self) -> Element<'_, crate::pages::Message> {
let Spacing {
space_xxs,
space_xs,
space_m,
..
} = cosmic::theme::spacing();
let active = self.icon_theme_active; let active = self.icon_theme_active;
let theme = cosmic::theme::active();
let theme = theme.cosmic();
cosmic::iced::widget::column![ cosmic::iced::widget::column![
// Export theme choice // Export theme choice
settings::section().add( settings::section().add(
@ -496,15 +500,15 @@ impl Page {
}) })
.collect(), .collect(),
) )
.row_spacing(theme.space_xs()) .row_spacing(space_xs)
.column_spacing(theme.space_xs()) .column_spacing(space_xs)
.apply(container) .apply(container)
.center_x(Length::Fill) .center_x(Length::Fill)
.into() .into()
]) ])
.spacing(theme.space_xxs()) .spacing(space_xxs)
] ]
.spacing(theme.space_m()) .spacing(space_m)
.width(Length::Fill) .width(Length::Fill)
.apply(Element::from) .apply(Element::from)
.map(crate::pages::Message::Appearance) .map(crate::pages::Message::Appearance)
@ -522,20 +526,14 @@ impl Page {
self.context_view = Some(ContextView::MonospaceFont); self.context_view = Some(ContextView::MonospaceFont);
self.font_search.clear(); self.font_search.clear();
return cosmic::task::message(crate::app::Message::OpenContextDrawer( return cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity));
self.entity,
fl!("monospace-font").into(),
));
} }
Message::DisplaySystemFont => { Message::DisplaySystemFont => {
self.context_view = Some(ContextView::SystemFont); self.context_view = Some(ContextView::SystemFont);
self.font_search.clear(); self.font_search.clear();
return cosmic::task::message(crate::app::Message::OpenContextDrawer( return cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity));
self.entity,
fl!("interface-font").into(),
));
} }
Message::FontConfig(message) => { Message::FontConfig(message) => {
@ -627,11 +625,8 @@ impl Page {
Message::AccentWindowHint(u) => { Message::AccentWindowHint(u) => {
needs_sync = true; needs_sync = true;
let (task, needs_update) = self.update_color_picker( let (task, needs_update) =
&u, self.update_color_picker(&u, ContextView::AccentWindowHint);
ContextView::AccentWindowHint,
fl!("window-hint-accent").into(),
);
tasks.push(task); tasks.push(task);
tasks.push(self.accent_window_hint.update::<app::Message>(u)); tasks.push(self.accent_window_hint.update::<app::Message>(u));
@ -718,11 +713,8 @@ impl Page {
} }
Message::ApplicationBackground(u) => { Message::ApplicationBackground(u) => {
let (task, needs_update) = self.update_color_picker( let (task, needs_update) =
&u, self.update_color_picker(&u, ContextView::ApplicationBackground);
ContextView::ApplicationBackground,
fl!("app-background").into(),
);
tasks.push(task); tasks.push(task);
tasks.push(self.application_background.update::<app::Message>(u)); tasks.push(self.application_background.update::<app::Message>(u));
@ -745,11 +737,8 @@ impl Page {
} }
Message::ContainerBackground(u) => { Message::ContainerBackground(u) => {
let (task, needs_update) = self.update_color_picker( let (task, needs_update) =
&u, self.update_color_picker(&u, ContextView::ContainerBackground);
ContextView::ContainerBackground,
fl!("container-background").into(),
);
tasks.push(task); tasks.push(task);
tasks.push(self.container_background.update::<app::Message>(u)); tasks.push(self.container_background.update::<app::Message>(u));
@ -772,11 +761,7 @@ impl Page {
} }
Message::CustomAccent(u) => { Message::CustomAccent(u) => {
let (task, needs_update) = self.update_color_picker( let (task, needs_update) = self.update_color_picker(&u, ContextView::CustomAccent);
&u,
ContextView::CustomAccent,
fl!("accent-color").into(),
);
tasks.push(task); tasks.push(task);
tasks.push(self.custom_accent.update::<app::Message>(u)); tasks.push(self.custom_accent.update::<app::Message>(u));
@ -797,11 +782,7 @@ impl Page {
} }
Message::InterfaceText(u) => { Message::InterfaceText(u) => {
let (task, needs_update) = self.update_color_picker( let (task, needs_update) = self.update_color_picker(&u, ContextView::InterfaceText);
&u,
ContextView::InterfaceText,
fl!("text-tint").into(),
);
tasks.push(task); tasks.push(task);
tasks.push(self.interface_text.update::<app::Message>(u)); tasks.push(self.interface_text.update::<app::Message>(u));
@ -822,11 +803,8 @@ impl Page {
} }
Message::ControlComponent(u) => { Message::ControlComponent(u) => {
let (task, needs_update) = self.update_color_picker( let (task, needs_update) =
&u, self.update_color_picker(&u, ContextView::ControlComponent);
ContextView::ControlComponent,
fl!("control-tint").into(),
);
tasks.push(task); tasks.push(task);
tasks.push(self.control_component.update::<app::Message>(u)); tasks.push(self.control_component.update::<app::Message>(u));
@ -1196,7 +1174,7 @@ impl Page {
self.context_view = Some(ContextView::IconsAndToolkit); self.context_view = Some(ContextView::IconsAndToolkit);
let mut tasks = Vec::new(); let mut tasks = Vec::new();
tasks.push(cosmic::task::message( tasks.push(cosmic::task::message(
crate::app::Message::OpenContextDrawer(self.entity, "".into()), crate::app::Message::OpenContextDrawer(self.entity),
)); ));
if !self.icons_fetched { if !self.icons_fetched {
self.icons_fetched = true; self.icons_fetched = true;
@ -1336,7 +1314,6 @@ impl Page {
&mut self, &mut self,
message: &ColorPickerUpdate, message: &ColorPickerUpdate,
context_view: ContextView, context_view: ContextView,
context_title: Cow<'static, str>,
) -> (Task<app::Message>, bool) { ) -> (Task<app::Message>, bool) {
let mut needs_update = false; let mut needs_update = false;
@ -1357,10 +1334,7 @@ impl Page {
ColorPickerUpdate::ToggleColorPicker => { ColorPickerUpdate::ToggleColorPicker => {
self.context_view = Some(context_view); self.context_view = Some(context_view);
cosmic::task::message(crate::app::Message::OpenContextDrawer( cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity))
self.entity,
context_title,
))
} }
_ => Task::none(), _ => Task::none(),
@ -1623,54 +1597,78 @@ impl page::Page<crate::pages::Message> for Page {
} }
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> { fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
let view = match self.context_view? { Some(match self.context_view? {
ContextView::AccentWindowHint => color_picker_context_view( ContextView::AccentWindowHint => context_drawer(
None, color_picker_context_view(
RESET_TO_DEFAULT.as_str().into(), None,
Message::AccentWindowHint, RESET_TO_DEFAULT.as_str().into(),
&self.accent_window_hint, Message::AccentWindowHint,
&self.accent_window_hint,
)
.map(crate::pages::Message::Appearance),
crate::pages::Message::CloseContextDrawer,
) )
.map(crate::pages::Message::Appearance), .title(fl!("window-hint-accent")),
ContextView::ApplicationBackground => color_picker_context_view( ContextView::ApplicationBackground => context_drawer(
None, color_picker_context_view(
RESET_TO_DEFAULT.as_str().into(), None,
Message::ApplicationBackground, RESET_TO_DEFAULT.as_str().into(),
&self.application_background, Message::ApplicationBackground,
&self.application_background,
)
.map(crate::pages::Message::Appearance),
crate::pages::Message::CloseContextDrawer,
) )
.map(crate::pages::Message::Appearance), .title(fl!("app-background")),
ContextView::ContainerBackground => color_picker_context_view( ContextView::ContainerBackground => context_drawer(
Some(fl!("container-background", "desc-detail").into()), color_picker_context_view(
fl!("container-background", "reset").into(), Some(fl!("container-background", "desc-detail").into()),
Message::ContainerBackground, fl!("container-background", "reset").into(),
&self.container_background, Message::ContainerBackground,
&self.container_background,
)
.map(crate::pages::Message::Appearance),
crate::pages::Message::CloseContextDrawer,
) )
.map(crate::pages::Message::Appearance), .title(fl!("container-background")),
ContextView::ControlComponent => color_picker_context_view( ContextView::ControlComponent => context_drawer(
None, color_picker_context_view(
RESET_TO_DEFAULT.as_str().into(), None,
Message::ControlComponent, RESET_TO_DEFAULT.as_str().into(),
&self.control_component, Message::ControlComponent,
&self.control_component,
)
.map(crate::pages::Message::Appearance),
crate::pages::Message::CloseContextDrawer,
) )
.map(crate::pages::Message::Appearance), .title(fl!("control-tint")),
ContextView::CustomAccent => color_picker_context_view( ContextView::CustomAccent => context_drawer(
None, color_picker_context_view(
RESET_TO_DEFAULT.as_str().into(), None,
Message::CustomAccent, RESET_TO_DEFAULT.as_str().into(),
&self.custom_accent, Message::CustomAccent,
&self.custom_accent,
)
.map(crate::pages::Message::Appearance),
crate::pages::Message::CloseContextDrawer,
) )
.map(crate::pages::Message::Appearance), .title(fl!("accent-color")),
ContextView::InterfaceText => color_picker_context_view( ContextView::InterfaceText => context_drawer(
None, color_picker_context_view(
RESET_TO_DEFAULT.as_str().into(), None,
Message::InterfaceText, RESET_TO_DEFAULT.as_str().into(),
&self.interface_text, Message::InterfaceText,
&self.interface_text,
)
.map(crate::pages::Message::Appearance),
crate::pages::Message::CloseContextDrawer,
) )
.map(crate::pages::Message::Appearance), .title(fl!("text-tint")),
ContextView::SystemFont => { ContextView::SystemFont => {
let filter = if self.font_search.is_empty() { let filter = if self.font_search.is_empty() {
@ -1678,16 +1676,21 @@ impl page::Page<crate::pages::Message> for Page {
} else { } else {
&self.font_filter &self.font_filter
}; };
let search_input = widget::search_input(fl!("type-to-search"), &self.font_search)
.on_input(Message::FontSearch)
.on_clear(Message::FontSearch(String::new()))
.apply(Element::from)
.map(crate::pages::Message::Appearance);
let current_font = cosmic::config::interface_font(); let current_font = cosmic::config::interface_font();
font_config::selection_context( context_drawer(
filter, font_config::selection_context(filter, current_font.family.as_str(), true)
&self.font_search, .map(crate::pages::Message::Appearance),
current_font.family.as_str(), crate::pages::Message::CloseContextDrawer,
true,
) )
.map(crate::pages::Message::Appearance) .title(fl!("interface-font"))
.header(search_input)
} }
ContextView::MonospaceFont => { ContextView::MonospaceFont => {
@ -1696,25 +1699,28 @@ impl page::Page<crate::pages::Message> for Page {
} else { } else {
&self.font_filter &self.font_filter
}; };
let search_input = widget::search_input(fl!("type-to-search"), &self.font_search)
.on_input(Message::FontSearch)
.on_clear(Message::FontSearch(String::new()))
.apply(Element::from)
.map(crate::pages::Message::Appearance);
let current_font = cosmic::config::monospace_font(); let current_font = cosmic::config::monospace_font();
font_config::selection_context( context_drawer(
filter, font_config::selection_context(filter, current_font.family.as_str(), false)
&self.font_search, .map(crate::pages::Message::Appearance),
current_font.family.as_str(), crate::pages::Message::CloseContextDrawer,
false,
) )
.map(crate::pages::Message::Appearance) .title(fl!("monospace-font"))
.header(search_input)
} }
ContextView::IconsAndToolkit => self.icons_and_toolkit(), ContextView::IconsAndToolkit => context_drawer(
}; self.icons_and_toolkit(),
crate::pages::Message::CloseContextDrawer,
Some(cosmic::app::context_drawer( ),
view, })
crate::pages::Message::CloseContextDrawer,
))
} }
} }
@ -1745,7 +1751,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
.title(fl!("mode-and-colors")) .title(fl!("mode-and-colors"))
.descriptions(descriptions) .descriptions(descriptions)
.view::<Page>(move |_binder, page, section| { .view::<Page>(move |_binder, page, section| {
let Spacing { space_xxs, .. } = cosmic::theme::active().cosmic().spacing; let Spacing { space_xxs, .. } = cosmic::theme::spacing();
let descriptions = &section.descriptions; let descriptions = &section.descriptions;
let palette = &page.theme_builder.palette.as_ref(); let palette = &page.theme_builder.palette.as_ref();
@ -1779,7 +1785,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
let accent_color_palette = cosmic::iced::widget::column![ let accent_color_palette = cosmic::iced::widget::column![
text::body(&descriptions[accent_color]), text::body(&descriptions[accent_color]),
scrollable( scrollable::horizontal(
accent_palette_row accent_palette_row
.push(if let Some(c) = page.custom_accent.get_applied_color() { .push(if let Some(c) = page.custom_accent.get_applied_color() {
container(color_button( container(color_button(
@ -1800,7 +1806,6 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
.padding([0, 0, 16, 0]) .padding([0, 0, 16, 0])
.spacing(16) .spacing(16)
) )
.direction(Direction::Horizontal(Scrollbar::new()))
] ]
.padding([16, 0, 0, 0]) .padding([16, 0, 0, 0])
.spacing(space_xxs); .spacing(space_xxs);

View file

@ -120,9 +120,7 @@ impl page::Page<crate::pages::Message> for Page {
} }
fn header_view(&self) -> Option<Element<'_, crate::pages::Message>> { fn header_view(&self) -> Option<Element<'_, crate::pages::Message>> {
let space_xxs = theme::active().cosmic().spacing.space_xxs; let content = row::with_capacity(1)
let content = row::with_capacity(2)
.spacing(space_xxs)
.push(button::standard(fl!("add-applet")).on_press(Message::AddAppletDrawer)) .push(button::standard(fl!("add-applet")).on_press(Message::AddAppletDrawer))
.apply(container) .apply(container)
.width(Length::Fill) .width(Length::Fill)
@ -134,16 +132,24 @@ impl page::Page<crate::pages::Message> for Page {
} }
fn context_drawer(&self) -> Option<ContextDrawer<pages::Message>> { fn context_drawer(&self) -> Option<ContextDrawer<pages::Message>> {
Some(cosmic::app::context_drawer( Some(match self.context {
match self.context { Some(ContextDrawerVariant::AddApplet) => {
Some(ContextDrawerVariant::AddApplet) => { let search_input = text_input::search_input(fl!("search-applets"), &self.search)
self.add_applet_view(crate::pages::Message::PanelApplet) .on_input(Message::Search)
} .on_paste(Message::Search)
.width(Length::Fixed(312.0))
.apply(Element::from)
.map(crate::pages::Message::PanelApplet);
None => return None, cosmic::app::context_drawer(
}, self.add_applet_view(crate::pages::Message::PanelApplet),
crate::pages::Message::CloseContextDrawer, crate::pages::Message::CloseContextDrawer,
)) )
.title(fl!("add-applet"))
.header(search_input)
}
None => return None,
})
} }
fn on_enter(&mut self) -> Task<crate::pages::Message> { fn on_enter(&mut self) -> Task<crate::pages::Message> {
@ -228,9 +234,8 @@ impl Page {
let cosmic::cosmic_theme::Spacing { let cosmic::cosmic_theme::Spacing {
space_xxxs, space_xxxs,
space_xs, space_xs,
space_l,
.. ..
} = theme::active().cosmic().spacing; } = theme::spacing();
let mut list_column = list_column(); let mut list_column = list_column();
let mut has_some = false; let mut has_some = false;
for info in self for info in self
@ -287,17 +292,7 @@ impl Page {
); );
} }
let search = text_input::search_input(fl!("search-applets"), &self.search) list_column.into()
.on_input(move |s| msg_map(Message::Search(s)))
.on_paste(move |s| msg_map(Message::Search(s)))
.width(Length::Fixed(312.0));
column::with_capacity(2)
.push(search)
.push(list_column)
.align_x(Alignment::Center)
.spacing(space_l)
.into()
} }
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
@ -421,10 +416,7 @@ impl Page {
} }
Message::AddAppletDrawer => { Message::AddAppletDrawer => {
self.context = Some(ContextDrawerVariant::AddApplet); self.context = Some(ContextDrawerVariant::AddApplet);
return cosmic::task::message(app::Message::OpenContextDrawer( return cosmic::task::message(app::Message::OpenContextDrawer(self.entity));
self.entity,
Cow::Owned(fl!("add-applet")),
));
} }
}; };
Task::none() Task::none()
@ -443,7 +435,7 @@ pub fn lists<
space_xxs, space_xxs,
space_xs, space_xs,
.. ..
} = theme::active().cosmic().spacing; } = theme::spacing();
let page = page.inner(); let page = page.inner();
let Some(config) = page.current_config.as_ref() else { let Some(config) = page.current_config.as_ref() else {
return Element::from(text::body(fl!("unknown"))); return Element::from(text::body(fl!("unknown")));
@ -642,7 +634,7 @@ impl<'a, Message: 'static + Clone> AppletReorderList<'a, Message> {
space_xxs, space_xxs,
space_xs, space_xs,
.. ..
} = theme::active().cosmic().spacing; } = theme::spacing();
let applet_buttons = info let applet_buttons = info
.clone() .clone()
.into_iter() .into_iter()
@ -737,7 +729,7 @@ impl<'a, Message: 'static + Clone> AppletReorderList<'a, Message> {
pos: Point, pos: Point,
offered_applet: Applet<'a>, offered_applet: Applet<'a>,
) -> Vec<Applet<'a>> { ) -> Vec<Applet<'a>> {
let space_xxs = theme::active().cosmic().spacing.space_xxs; let space_xxs = theme::spacing().space_xxs;
let mut reordered: Vec<_> = self.info.clone(); let mut reordered: Vec<_> = self.info.clone();
if !layout.bounds().contains(pos) { if !layout.bounds().contains(pos) {
@ -916,7 +908,7 @@ where
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
viewport: &Rectangle, viewport: &Rectangle,
) -> event::Status { ) -> event::Status {
let space_xxs = theme::active().cosmic().spacing.space_xxs; let space_xxs = theme::spacing().space_xxs;
let mut ret = match self.inner.as_widget_mut().on_event( let mut ret = match self.inner.as_widget_mut().on_event(
&mut tree.children[0], &mut tree.children[0],
event.clone(), event.clone(),

View file

@ -290,6 +290,7 @@ impl page::Page<crate::pages::Message> for Page {
}, },
crate::pages::Message::CloseContextDrawer, crate::pages::Message::CloseContextDrawer,
) )
.title(fl!("color-picker"))
}) })
} }
} }
@ -770,10 +771,7 @@ impl Page {
Message::ColorAddContext => { Message::ColorAddContext => {
self.context_view = Some(ContextView::AddColor); self.context_view = Some(ContextView::AddColor);
self.selection.active = Choice::Color(wallpaper::Color::Single([0., 0., 0.])); self.selection.active = Choice::Color(wallpaper::Color::Single([0., 0., 0.]));
return cosmic::task::message(crate::app::Message::OpenContextDrawer( return cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity));
self.entity,
fl!("color-picker").into(),
));
} }
Message::ColorRemove(color) => { Message::ColorRemove(color) => {

View file

@ -7,7 +7,7 @@ pub mod arrangement;
use crate::{app, pages}; use crate::{app, pages};
use arrangement::Arrangement; use arrangement::Arrangement;
use cosmic::iced::{Alignment, Length, time}; use cosmic::iced::{Alignment, Length, time};
use cosmic::iced_widget::scrollable::{Direction, RelativeOffset, Scrollbar}; use cosmic::iced_widget::scrollable::RelativeOffset;
use cosmic::widget::{ use cosmic::widget::{
self, column, container, dropdown, list_column, segmented_button, tab_bar, text, toggler, self, column, container, dropdown, list_column, segmented_button, tab_bar, text, toggler,
}; };
@ -1144,7 +1144,7 @@ pub fn display_arrangement() -> Section<crate::pages::Message> {
let descriptions = &section.descriptions; let descriptions = &section.descriptions;
let cosmic::cosmic_theme::Spacing { let cosmic::cosmic_theme::Spacing {
space_xxs, space_m, .. space_xxs, space_m, ..
} = cosmic::theme::active().cosmic().spacing; } = cosmic::theme::spacing();
column() column()
.push( .push(
@ -1159,10 +1159,9 @@ pub fn display_arrangement() -> Section<crate::pages::Message> {
.on_placement(|id, x, y| { .on_placement(|id, x, y| {
pages::Message::Displays(Message::Position(id, x, y)) pages::Message::Displays(Message::Position(id, x, y))
}) })
.apply(widget::scrollable) .apply(widget::scrollable::horizontal)
.id(page.display_arrangement_scrollable.clone()) .id(page.display_arrangement_scrollable.clone())
.width(Length::Shrink) .width(Length::Shrink)
.direction(Direction::Horizontal(Scrollbar::new()))
.apply(container) .apply(container)
.center_x(Length::Fill) .center_x(Length::Fill)
}) })
@ -1192,7 +1191,6 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
.descriptions(descriptions) .descriptions(descriptions)
.view::<Page>(move |_binder, page, section| { .view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions; let descriptions = &section.descriptions;
let theme = cosmic::theme::active();
let Some(&active_id) = page.display_tabs.active_data::<OutputKey>() else { let Some(&active_id) = page.display_tabs.active_data::<OutputKey>() else {
return column().into(); return column().into();
@ -1296,7 +1294,7 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
items items
}); });
let mut content = column().spacing(theme.cosmic().space_xs()); let mut content = column().spacing(cosmic::theme::spacing().space_xs);
if page.list.outputs.len() > 1 { if page.list.outputs.len() > 1 {
let display_switcher = tab_bar::horizontal(&page.display_tabs) let display_switcher = tab_bar::horizontal(&page.display_tabs)

View file

@ -7,7 +7,7 @@ use std::cmp;
use cosmic::{ use cosmic::{
Apply, Element, Task, Apply, Element, Task,
app::ContextDrawer, app::{ContextDrawer, context_drawer},
cosmic_config::{self, ConfigSet}, cosmic_config::{self, ConfigSet},
iced::{Alignment, Color, Length}, iced::{Alignment, Color, Length},
iced_core::Border, iced_core::Border,
@ -298,19 +298,33 @@ impl page::Page<crate::pages::Message> for Page {
} }
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> { fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
self.context.as_ref().map(|context| { self.context.as_ref().map(|context| match context {
cosmic::app::context_drawer( Context::ShowInputSourcesContext => {
match context { let search = widget::search_input(fl!("type-to-search"), &self.input_source_search)
Context::ShowInputSourcesContext => self.add_input_source_view(), .on_input(Message::InputSourceSearch)
Context::SpecialCharacter(special_key) => self .on_clear(Message::InputSourceSearch(String::new()))
.special_character_key_view(*special_key) .apply(Element::from)
.map(crate::pages::Message::Keyboard), .map(crate::pages::Message::Keyboard);
Context::NumlockState => self
.numlock_state_view() context_drawer(
.map(crate::pages::Message::Keyboard), self.add_input_source_view(),
}, crate::pages::Message::CloseContextDrawer,
)
.title(fl!("keyboard-sources", "add"))
.header(search)
}
Context::SpecialCharacter(special_key) => context_drawer(
self.special_character_key_view(*special_key)
.map(crate::pages::Message::Keyboard),
crate::pages::Message::CloseContextDrawer, crate::pages::Message::CloseContextDrawer,
) )
.title(special_key.title()),
Context::NumlockState => context_drawer(
self.numlock_state_view()
.map(crate::pages::Message::Keyboard),
crate::pages::Message::CloseContextDrawer,
)
.title(fl!("keyboard-numlock-boot", "set")),
}) })
} }
@ -487,10 +501,7 @@ impl Page {
Message::ShowInputSourcesContext => { Message::ShowInputSourcesContext => {
self.context = Some(Context::ShowInputSourcesContext); self.context = Some(Context::ShowInputSourcesContext);
return cosmic::task::message(crate::app::Message::OpenContextDrawer( return cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity));
self.entity,
fl!("keyboard-sources", "add").into(),
));
} }
Message::ExpandInputSourcePopover(value) => { Message::ExpandInputSourcePopover(value) => {
@ -499,18 +510,12 @@ impl Page {
Message::OpenSpecialCharacterContext(key) => { Message::OpenSpecialCharacterContext(key) => {
self.context = Some(Context::SpecialCharacter(key)); self.context = Some(Context::SpecialCharacter(key));
return cosmic::task::message(crate::app::Message::OpenContextDrawer( return cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity));
self.entity,
key.title().into(),
));
} }
Message::OpenNumlockContext => { Message::OpenNumlockContext => {
self.context = Some(Context::NumlockState); self.context = Some(Context::NumlockState);
return cosmic::task::message(crate::app::Message::OpenContextDrawer( return cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity));
self.entity,
fl!("keyboard-numlock-boot", "set").into(),
));
} }
Message::SpecialCharacterSelect(id) => { Message::SpecialCharacterSelect(id) => {
@ -553,11 +558,7 @@ impl Page {
} }
pub fn add_input_source_view(&self) -> Element<'_, crate::pages::Message> { pub fn add_input_source_view(&self) -> Element<'_, crate::pages::Message> {
let space_l = theme::active().cosmic().spacing.space_l; let space_l = theme::spacing().space_l;
let search = widget::search_input(fl!("type-to-search"), &self.input_source_search)
.on_input(Message::InputSourceSearch)
.on_clear(Message::InputSourceSearch(String::new()));
let toggler = settings::item::builder(fl!("show-extended-input-sources")).toggler( let toggler = settings::item::builder(fl!("show-extended-input-sources")).toggler(
self.show_extended_input_sources, self.show_extended_input_sources,
@ -577,9 +578,7 @@ impl Page {
} }
widget::column() widget::column()
.padding([2, 0])
.spacing(space_l) .spacing(space_l)
.push(search)
.push(toggler) .push(toggler)
.push(list) .push(list)
.apply(Element::from) .apply(Element::from)
@ -715,7 +714,7 @@ fn input_sources() -> Section<crate::pages::Message> {
.on_press(Message::ShowInputSourcesContext); .on_press(Message::ShowInputSourcesContext);
widget::column::with_capacity(2) widget::column::with_capacity(2)
.spacing(cosmic::theme::active().cosmic().space_xxs()) .spacing(cosmic::theme::spacing().space_xxs)
.push(section) .push(section)
.push( .push(
widget::container(add_input_source) widget::container(add_input_source)
@ -800,7 +799,6 @@ fn keyboard_typing_assist() -> Section<crate::pages::Message> {
.descriptions(descriptions) .descriptions(descriptions)
.view::<Page>(move |_binder, page, section| { .view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions; let descriptions = &section.descriptions;
let theme = cosmic::theme::active();
settings::section() settings::section()
.title(&section.title) .title(&section.title)
@ -819,7 +817,7 @@ fn keyboard_typing_assist() -> Section<crate::pages::Message> {
row::with_capacity(3) row::with_capacity(3)
.align_y(Alignment::Center) .align_y(Alignment::Center)
.spacing(theme.cosmic().space_s()) .spacing(cosmic::theme::spacing().space_s)
.push(widget::text::body(&descriptions[short])) .push(widget::text::body(&descriptions[short]))
.push(delay_slider) .push(delay_slider)
.push(widget::text::body(&descriptions[long])) .push(widget::text::body(&descriptions[long]))
@ -839,7 +837,7 @@ fn keyboard_typing_assist() -> Section<crate::pages::Message> {
row::with_capacity(3) row::with_capacity(3)
.align_y(Alignment::Center) .align_y(Alignment::Center)
.spacing(theme.cosmic().space_s()) .spacing(cosmic::theme::spacing().space_s)
.push(widget::text::body(&descriptions[slow])) .push(widget::text::body(&descriptions[slow]))
.push(rate_slider) .push(rate_slider)
.push(widget::text::body(&descriptions[fast])) .push(widget::text::body(&descriptions[fast]))

View file

@ -459,7 +459,7 @@ impl Model {
self.replace_dialog = None; self.replace_dialog = None;
let mut tasks = vec![cosmic::task::message( let mut tasks = vec![cosmic::task::message(
crate::app::Message::OpenContextDrawer(self.entity, "".into()), crate::app::Message::OpenContextDrawer(self.entity),
)]; )];
if let Some(model) = self.shortcut_models.get(0) { if let Some(model) = self.shortcut_models.get(0) {
@ -572,7 +572,7 @@ fn context_drawer<'a>(
space_xs, space_xs,
space_l, space_l,
.. ..
} = theme::active().cosmic().spacing; } = theme::spacing();
let model = &shortcuts[id]; let model = &shortcuts[id];

View file

@ -203,10 +203,7 @@ impl Page {
Message::ShortcutContext => { Message::ShortcutContext => {
self.add_shortcut.enable(); self.add_shortcut.enable();
return Task::batch(vec![ return Task::batch(vec![
cosmic::task::message(crate::app::Message::OpenContextDrawer( cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity)),
self.entity,
fl!("custom-shortcuts", "context").into(),
)),
widget::text_input::focus(self.name_id.clone()), widget::text_input::focus(self.name_id.clone()),
]); ]);
} }
@ -363,11 +360,14 @@ impl page::Page<crate::pages::Message> for Page {
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> { fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
if self.add_shortcut.active { if self.add_shortcut.active {
Some(cosmic::app::context_drawer( Some(
self.add_keybinding_context() cosmic::app::context_drawer(
.map(crate::pages::Message::CustomShortcuts), self.add_keybinding_context()
crate::pages::Message::CloseContextDrawer, .map(crate::pages::Message::CustomShortcuts),
)) crate::pages::Message::CloseContextDrawer,
)
.title(fl!("custom-shortcuts", "context")),
)
} else { } else {
self.model.context_drawer(|msg| { self.model.context_drawer(|msg| {
crate::pages::Message::CustomShortcuts(Message::Shortcut(msg)) crate::pages::Message::CustomShortcuts(Message::Shortcut(msg))

View file

@ -168,11 +168,21 @@ impl page::Page<crate::pages::Message> for Page {
fn context_drawer(&self) -> Option<ContextDrawer<crate::pages::Message>> { fn context_drawer(&self) -> Option<ContextDrawer<crate::pages::Message>> {
if self.timezone_context { if self.timezone_context {
return Some(cosmic::app::context_drawer( let search = widget::search_input(fl!("type-to-search"), &self.timezone_search)
self.timezone_context_view() .on_input(Message::TimezoneSearch)
.map(crate::pages::Message::from), .on_clear(Message::TimezoneSearch(String::new()))
crate::pages::Message::CloseContextDrawer, .apply(Element::from)
)); .map(crate::pages::Message::DateAndTime);
return Some(
cosmic::app::context_drawer(
self.timezone_context_view()
.map(crate::pages::Message::from),
crate::pages::Message::CloseContextDrawer,
)
.title(fl!("time-zone"))
.header(search),
);
} }
None None
@ -185,10 +195,7 @@ impl Page {
Message::TimezoneContext => { Message::TimezoneContext => {
self.timezone_search.clear(); self.timezone_search.clear();
self.timezone_context = true; self.timezone_context = true;
return cosmic::task::message(crate::app::Message::OpenContextDrawer( return cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity));
self.entity,
fl!("time-zone").into(),
));
} }
Message::MilitaryTime(enable) => { Message::MilitaryTime(enable) => {
@ -317,12 +324,6 @@ impl Page {
} }
fn timezone_context_view(&self) -> Element<'_, crate::pages::Message> { fn timezone_context_view(&self) -> Element<'_, crate::pages::Message> {
let space_l = cosmic::theme::active().cosmic().spacing.space_l;
let search = widget::search_input(fl!("type-to-search"), &self.timezone_search)
.on_input(Message::TimezoneSearch)
.on_clear(Message::TimezoneSearch(String::new()));
let mut list = widget::list_column(); let mut list = widget::list_column();
let search_input = &self.timezone_search.trim().to_lowercase(); let search_input = &self.timezone_search.trim().to_lowercase();
@ -333,12 +334,7 @@ impl Page {
} }
} }
widget::column() list.apply(Element::from)
.padding([2, 0])
.spacing(space_l)
.push(search)
.push(list)
.apply(Element::from)
.map(crate::pages::Message::DateAndTime) .map(crate::pages::Message::DateAndTime)
} }

View file

@ -6,7 +6,7 @@ use std::rc::Rc;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use cosmic::app::ContextDrawer; use cosmic::app::{ContextDrawer, context_drawer};
use cosmic::iced::{Alignment, Border, Color, Length}; use cosmic::iced::{Alignment, Border, Color, Length};
use cosmic::iced_core::text::Wrapping; use cosmic::iced_core::text::Wrapping;
use cosmic::widget::{self, button, container}; use cosmic::widget::{self, button, container};
@ -154,14 +154,45 @@ impl page::Page<crate::pages::Message> for Page {
} }
fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> { fn context_drawer(&self) -> Option<ContextDrawer<'_, crate::pages::Message>> {
Some(cosmic::app::context_drawer( Some(match self.context.as_ref()? {
match self.context.as_ref()? { ContextView::AddLanguage => {
ContextView::AddLanguage => self.add_language_view(), let search = widget::search_input(fl!("type-to-search"), &self.add_language_search)
ContextView::Region => self.region_view(), .on_input(Message::AddLanguageSearch)
.on_clear(Message::AddLanguageSearch(String::new()))
.apply(Element::from)
.map(crate::pages::Message::from);
let install_additional_button =
widget::button::standard(fl!("install-additional-languages"))
.on_press(Message::InstallAdditionalLanguages)
.apply(widget::container)
.width(Length::Fill)
.align_x(Alignment::End)
.apply(Element::from)
.map(crate::pages::Message::from);
context_drawer(
self.add_language_view().map(crate::pages::Message::from),
crate::pages::Message::CloseContextDrawer,
)
.title(fl!("add-language", "context"))
.header(search)
.footer(install_additional_button)
} }
.map(crate::pages::Message::from), ContextView::Region => {
crate::pages::Message::CloseContextDrawer, let search = widget::search_input(fl!("type-to-search"), &self.add_language_search)
)) .on_input(Message::AddLanguageSearch)
.on_clear(Message::AddLanguageSearch(String::new()))
.apply(Element::from)
.map(crate::pages::Message::from);
context_drawer(
self.region_view().map(crate::pages::Message::from),
crate::pages::Message::CloseContextDrawer,
)
.title(fl!("region"))
.header(search)
}
})
} }
} }
@ -208,10 +239,7 @@ impl Page {
Message::AddLanguageContext => { Message::AddLanguageContext => {
self.context = Some(ContextView::AddLanguage); self.context = Some(ContextView::AddLanguage);
return cosmic::Task::done(crate::app::Message::OpenContextDrawer( return cosmic::Task::done(crate::app::Message::OpenContextDrawer(self.entity));
self.entity,
fl!("add-language", "context").into(),
));
} }
Message::AddLanguageSearch(search) => { Message::AddLanguageSearch(search) => {
@ -253,10 +281,7 @@ impl Page {
Message::RegionContext => { Message::RegionContext => {
self.context = Some(ContextView::Region); self.context = Some(ContextView::Region);
return cosmic::Task::done(crate::app::Message::OpenContextDrawer( return cosmic::Task::done(crate::app::Message::OpenContextDrawer(self.entity));
self.entity,
fl!("region").into(),
));
} }
Message::SourceContext(context_message) => { Message::SourceContext(context_message) => {
@ -310,12 +335,6 @@ impl Page {
} }
fn add_language_view(&self) -> cosmic::Element<'_, crate::pages::Message> { fn add_language_view(&self) -> cosmic::Element<'_, crate::pages::Message> {
let cosmic::cosmic_theme::Spacing { space_l, .. } = theme::active().cosmic().spacing;
let search = widget::search_input(fl!("type-to-search"), &self.add_language_search)
.on_input(Message::AddLanguageSearch)
.on_clear(Message::AddLanguageSearch(String::new()));
let mut list = widget::list_column(); let mut list = widget::list_column();
let search_input = &self.add_language_search.trim().to_lowercase(); let search_input = &self.add_language_search.trim().to_lowercase();
@ -370,21 +389,7 @@ impl Page {
} }
} }
let install_additional_button = list.apply(Element::from).map(crate::pages::Message::Region)
widget::button::standard(fl!("install-additional-languages"))
.on_press(Message::InstallAdditionalLanguages)
.apply(widget::container)
.width(Length::Fill)
.align_x(Alignment::End);
widget::column()
.padding([2, 0])
.spacing(space_l)
.push(search)
.push(list)
.push(install_additional_button)
.apply(Element::from)
.map(crate::pages::Message::Region)
} }
fn formatted_date(&self) -> String { fn formatted_date(&self) -> String {
@ -519,17 +524,11 @@ impl Page {
} }
fn region_view(&self) -> cosmic::Element<'_, crate::pages::Message> { fn region_view(&self) -> cosmic::Element<'_, crate::pages::Message> {
let space_l = theme::active().cosmic().spacing.space_l;
let svg_accent = Rc::new(|theme: &cosmic::Theme| { let svg_accent = Rc::new(|theme: &cosmic::Theme| {
let color = theme.cosmic().accent_color().into(); let color = theme.cosmic().accent_color().into();
cosmic::widget::svg::Style { color: Some(color) } cosmic::widget::svg::Style { color: Some(color) }
}); });
let search = widget::search_input(fl!("type-to-search"), &self.add_language_search)
.on_input(Message::AddLanguageSearch)
.on_clear(Message::AddLanguageSearch(String::new()));
let mut list = widget::list_column(); let mut list = widget::list_column();
let search_input = &self.add_language_search.trim().to_lowercase(); let search_input = &self.add_language_search.trim().to_lowercase();
@ -576,13 +575,7 @@ impl Page {
} }
} }
widget::column() list.apply(Element::from).map(crate::pages::Message::Region)
.padding([2, 0])
.spacing(space_l)
.push(search)
.push(list)
.apply(Element::from)
.map(crate::pages::Message::Region)
} }
} }
@ -643,7 +636,7 @@ mod preferred_languages {
.push(description) .push(description)
.push(content) .push(content)
.push(add_language_button) .push(add_language_button)
.spacing(cosmic::theme::active().cosmic().spacing.space_xxs) .spacing(cosmic::theme::spacing().space_xxs)
.apply(cosmic::Element::from) .apply(cosmic::Element::from)
.map(Into::into) .map(Into::into)
}) })