fix(wallpapers): use context drawer for color picker
This commit is contained in:
parent
6df4650ff9
commit
544da2bdc8
4 changed files with 157 additions and 173 deletions
|
|
@ -603,12 +603,6 @@ impl cosmic::Application for SettingsApp {
|
|||
return page.dnd_icon();
|
||||
}
|
||||
|
||||
if let Some(page) = self.pages.page::<desktop::wallpaper::Page>() {
|
||||
if id == page.color_dialog {
|
||||
return page.show_color_dialog();
|
||||
}
|
||||
}
|
||||
|
||||
panic!("unknown window ID: {id:?}");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ use slotmap::SlotMap;
|
|||
use tokio::io::AsyncBufReadExt;
|
||||
|
||||
use crate::app;
|
||||
use crate::widget::color_picker_context_view;
|
||||
|
||||
use super::wallpaper::widgets::color_image;
|
||||
|
||||
|
|
@ -423,40 +424,6 @@ impl Page {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn color_picker_context_view(
|
||||
&self,
|
||||
description: Option<Cow<'static, str>>,
|
||||
reset: Cow<'static, str>,
|
||||
on_update: fn(ColorPickerUpdate) -> Message,
|
||||
model: impl Fn(&Self) -> &ColorPickerModel,
|
||||
) -> Element<'_, crate::pages::Message> {
|
||||
cosmic::widget::column()
|
||||
.push_maybe(description.map(|description| text::body(description).width(Length::Fill)))
|
||||
.push(
|
||||
model(self)
|
||||
.builder(on_update)
|
||||
.reset_label(reset)
|
||||
.height(Length::Fixed(158.0))
|
||||
.build(
|
||||
fl!("recent-colors"),
|
||||
fl!("copy-to-clipboard"),
|
||||
fl!("copied-to-clipboard"),
|
||||
)
|
||||
.apply(container)
|
||||
.width(Length::Fixed(248.0))
|
||||
.align_x(alignment::Horizontal::Center)
|
||||
.apply(container)
|
||||
.width(Length::Fill)
|
||||
.align_x(alignment::Horizontal::Center),
|
||||
)
|
||||
.padding(self.theme_builder.spacing.space_l)
|
||||
.align_items(cosmic::iced_core::Alignment::Center)
|
||||
.spacing(self.theme_builder.spacing.space_m)
|
||||
.width(Length::Fill)
|
||||
.apply(Element::from)
|
||||
.map(crate::pages::Message::Appearance)
|
||||
}
|
||||
|
||||
fn experimental_context_view(&self) -> Element<'_, crate::pages::Message> {
|
||||
let active = self.icon_theme_active;
|
||||
let theme = cosmic::theme::active();
|
||||
|
|
@ -1084,49 +1051,55 @@ impl page::Page<crate::pages::Message> for Page {
|
|||
|
||||
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
|
||||
let view = match self.context_view? {
|
||||
ContextView::AccentWindowHint => self.color_picker_context_view(
|
||||
ContextView::AccentWindowHint => color_picker_context_view(
|
||||
None,
|
||||
RESET_TO_DEFAULT.as_str().into(),
|
||||
Message::AccentWindowHint,
|
||||
|this| &this.accent_window_hint,
|
||||
),
|
||||
&self.accent_window_hint,
|
||||
)
|
||||
.map(crate::pages::Message::Appearance),
|
||||
|
||||
ContextView::ApplicationBackground => self.color_picker_context_view(
|
||||
ContextView::ApplicationBackground => color_picker_context_view(
|
||||
None,
|
||||
RESET_TO_DEFAULT.as_str().into(),
|
||||
Message::ApplicationBackground,
|
||||
|this| &this.application_background,
|
||||
),
|
||||
&self.application_background,
|
||||
)
|
||||
.map(crate::pages::Message::Appearance),
|
||||
|
||||
ContextView::ContainerBackground => self.color_picker_context_view(
|
||||
ContextView::ContainerBackground => color_picker_context_view(
|
||||
Some(fl!("container-background", "desc-detail").into()),
|
||||
fl!("container-background", "reset").into(),
|
||||
Message::ContainerBackground,
|
||||
|this| &this.container_background,
|
||||
),
|
||||
&self.container_background,
|
||||
)
|
||||
.map(crate::pages::Message::Appearance),
|
||||
|
||||
ContextView::ControlComponent => self.color_picker_context_view(
|
||||
ContextView::ControlComponent => color_picker_context_view(
|
||||
None,
|
||||
RESET_TO_DEFAULT.as_str().into(),
|
||||
Message::ControlComponent,
|
||||
|this| &this.control_component,
|
||||
),
|
||||
&self.control_component,
|
||||
)
|
||||
.map(crate::pages::Message::Appearance),
|
||||
|
||||
ContextView::CustomAccent => self.color_picker_context_view(
|
||||
ContextView::CustomAccent => color_picker_context_view(
|
||||
None,
|
||||
RESET_TO_DEFAULT.as_str().into(),
|
||||
Message::CustomAccent,
|
||||
|this| &this.custom_accent,
|
||||
),
|
||||
&self.custom_accent,
|
||||
)
|
||||
.map(crate::pages::Message::Appearance),
|
||||
|
||||
ContextView::Experimental => self.experimental_context_view(),
|
||||
|
||||
ContextView::InterfaceText => self.color_picker_context_view(
|
||||
ContextView::InterfaceText => color_picker_context_view(
|
||||
None,
|
||||
RESET_TO_DEFAULT.as_str().into(),
|
||||
Message::InterfaceText,
|
||||
|this| &this.interface_text,
|
||||
),
|
||||
&self.interface_text,
|
||||
)
|
||||
.map(crate::pages::Message::Appearance),
|
||||
};
|
||||
|
||||
Some(view)
|
||||
|
|
|
|||
|
|
@ -87,16 +87,14 @@ pub enum Message {
|
|||
ChangeCategory(Category),
|
||||
/// Changes the displayed images in the wallpaper view.
|
||||
ChangeFolder(Context),
|
||||
/// Creates a color dialog
|
||||
ColorAddDialog,
|
||||
/// Handles messages from the color dialog.
|
||||
ColorDialogUpdate(ColorPickerUpdate),
|
||||
ColorAdd(ColorPickerUpdate),
|
||||
/// Creates a color context drawer
|
||||
ColorAddContext,
|
||||
/// Removes a custom color from the color view.
|
||||
ColorRemove(wallpaper::Color),
|
||||
/// Selects a color in the color view.
|
||||
ColorSelect(wallpaper::Color),
|
||||
/// Handles the drag message in the color dialog.
|
||||
DragColorDialog,
|
||||
/// Sets the wallpaper fit parameter.
|
||||
Fit(usize),
|
||||
/// Adds a new custom image to the wallpaper view.
|
||||
|
|
@ -141,8 +139,16 @@ pub enum Category {
|
|||
Wallpapers,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum ContextView {
|
||||
AddColor,
|
||||
}
|
||||
|
||||
/// The page struct for the wallpaper view.
|
||||
pub struct Page {
|
||||
/// Whether to show a context drawer.
|
||||
context_view: Option<ContextView>,
|
||||
|
||||
/// Whether to show the tab_bar or not.
|
||||
show_tab_bar: bool,
|
||||
|
||||
|
|
@ -160,9 +166,6 @@ pub struct Page {
|
|||
/// Model for the category dropdown, which has categories and recent folders.
|
||||
categories: dropdown::multi::Model<String, Category>,
|
||||
|
||||
/// The window ID of the color dialog.
|
||||
pub color_dialog: window::Id,
|
||||
|
||||
/// The color model updated by the color dialog.
|
||||
color_model: ColorPickerModel,
|
||||
|
||||
|
|
@ -252,6 +255,18 @@ impl page::Page<crate::pages::Message> for Page {
|
|||
})))
|
||||
})
|
||||
}
|
||||
|
||||
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,
|
||||
)
|
||||
.map(crate::pages::Message::DesktopWallpaper),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
|
|
@ -259,6 +274,7 @@ impl page::AutoBind<crate::pages::Message> for Page {}
|
|||
impl Default for Page {
|
||||
fn default() -> Self {
|
||||
let mut page = Page {
|
||||
context_view: None,
|
||||
show_tab_bar: false,
|
||||
active_output: None,
|
||||
cached_display_handle: None,
|
||||
|
|
@ -290,7 +306,6 @@ impl Default for Page {
|
|||
categories
|
||||
},
|
||||
wallpaper_service_config: wallpaper::Config::default(),
|
||||
color_dialog: window::Id::unique(),
|
||||
color_model: ColorPickerModel::new(fl!("hex"), fl!("rgb"), None, Some(Color::WHITE)),
|
||||
config: Config::new(),
|
||||
fit_options: vec![fl!("fill"), fl!("fit-to-screen")],
|
||||
|
|
@ -669,46 +684,8 @@ impl Page {
|
|||
}
|
||||
}
|
||||
|
||||
Message::DragColorDialog => {
|
||||
return cosmic::iced_sctk::commands::window::start_drag_window(self.color_dialog)
|
||||
}
|
||||
|
||||
Message::CacheDisplayImage => self.cache_display_image(),
|
||||
|
||||
Message::ColorDialogUpdate(update) => {
|
||||
let cmd = match update {
|
||||
ColorPickerUpdate::AppliedColor
|
||||
| ColorPickerUpdate::Cancel
|
||||
| ColorPickerUpdate::Reset => {
|
||||
if let Some(color) = self.color_model.get_applied_color() {
|
||||
let color = wallpaper::Color::Single([color.r, color.g, color.b]);
|
||||
|
||||
if let Err(why) = self.config.add_custom_color(color.clone()) {
|
||||
tracing::error!(?why, "could not set custom color");
|
||||
}
|
||||
|
||||
self.selection.add_custom_color(color);
|
||||
}
|
||||
|
||||
close_window(self.color_dialog)
|
||||
}
|
||||
|
||||
ColorPickerUpdate::ActionFinished => {
|
||||
let _res = self
|
||||
.color_model
|
||||
.update::<crate::app::Message>(ColorPickerUpdate::AppliedColor);
|
||||
Command::none()
|
||||
}
|
||||
|
||||
_ => Command::none(),
|
||||
};
|
||||
|
||||
return Command::batch(vec![
|
||||
cmd,
|
||||
self.color_model.update::<crate::app::Message>(update),
|
||||
]);
|
||||
}
|
||||
|
||||
Message::ChangeFolder(mut context) => {
|
||||
// Reassign custom colors and images to the new context.
|
||||
std::mem::swap(&mut context, &mut self.selection);
|
||||
|
|
@ -730,8 +707,38 @@ impl Page {
|
|||
self.select_first_wallpaper();
|
||||
}
|
||||
|
||||
Message::ColorAddDialog => {
|
||||
return get_window(color_picker_window_settings(self.color_dialog));
|
||||
Message::ColorAdd(message) => {
|
||||
match message {
|
||||
ColorPickerUpdate::ActionFinished => {
|
||||
let _res = self
|
||||
.color_model
|
||||
.update::<crate::app::Message>(ColorPickerUpdate::AppliedColor);
|
||||
|
||||
if let Some(color) = self.color_model.get_applied_color() {
|
||||
let color = wallpaper::Color::Single([color.r, color.g, color.b]);
|
||||
|
||||
if let Err(why) = self.config.add_custom_color(color.clone()) {
|
||||
tracing::error!(?why, "could not set custom color");
|
||||
}
|
||||
|
||||
self.selection.add_custom_color(color.clone());
|
||||
self.selection.active = Choice::Color(color);
|
||||
self.cached_display_handle = None;
|
||||
self.context_view = None;
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
return self.color_model.update::<crate::app::Message>(message);
|
||||
}
|
||||
|
||||
Message::ColorAddContext => {
|
||||
self.context_view = Some(ContextView::AddColor);
|
||||
return cosmic::command::message(crate::app::Message::OpenContextDrawer(
|
||||
fl!("color-picker").into(),
|
||||
));
|
||||
}
|
||||
|
||||
Message::ColorRemove(color) => {
|
||||
|
|
@ -1053,15 +1060,6 @@ impl Page {
|
|||
|
||||
self.cache_display_image();
|
||||
}
|
||||
|
||||
pub fn show_color_dialog(&self) -> Element<crate::app::Message> {
|
||||
color_picker_view(
|
||||
&self.color_model,
|
||||
Message::DragColorDialog,
|
||||
Message::ColorDialogUpdate,
|
||||
)
|
||||
.map(|m| crate::app::Message::PageMessage(crate::pages::Message::DesktopWallpaper(m)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
|
@ -1264,7 +1262,7 @@ pub fn settings() -> Section<crate::pages::Message> {
|
|||
let add_button =
|
||||
if let Some(Category::Colors | Category::Wallpapers) = page.categories.selected {
|
||||
let (text, message) = if Some(Category::Colors) == page.categories.selected {
|
||||
(fl!("add-color"), Message::ColorAddDialog)
|
||||
(fl!("add-color"), Message::ColorAddContext)
|
||||
} else {
|
||||
(fl!("add-image"), Message::ImageAddDialog)
|
||||
};
|
||||
|
|
@ -1329,62 +1327,42 @@ pub fn settings() -> Section<crate::pages::Message> {
|
|||
})
|
||||
}
|
||||
|
||||
fn color_picker_window_settings(window_id: window::Id) -> SctkWindowSettings {
|
||||
SctkWindowSettings {
|
||||
window_id,
|
||||
app_id: Some("com.system76.CosmicSettings".to_string()),
|
||||
title: Some(fl!("color-picker")),
|
||||
parent: Some(window::Id::MAIN),
|
||||
autosize: false,
|
||||
size_limits: layout::Limits::NONE
|
||||
.min_width(300.0)
|
||||
.max_width(800.0)
|
||||
.min_height(520.0)
|
||||
.max_height(520.0),
|
||||
size: (300, 520),
|
||||
resizable: Some(8.0),
|
||||
client_decorations: true,
|
||||
transparent: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
// // TODO: Reuse with the appearance page
|
||||
// pub fn color_picker_view<Message: Clone + 'static>(
|
||||
// model: &ColorPickerModel,
|
||||
// on_drag: Message,
|
||||
// on_message: fn(ColorPickerUpdate) -> Message,
|
||||
// ) -> Element<Message> {
|
||||
// let header = cosmic::widget::header_bar()
|
||||
// .title(fl!("color-picker"))
|
||||
// .on_close(on_message(ColorPickerUpdate::AppliedColor))
|
||||
// .on_drag(on_drag);
|
||||
|
||||
// TODO: Reuse with the appearance page
|
||||
pub fn color_picker_view<Message: Clone + 'static>(
|
||||
model: &ColorPickerModel,
|
||||
on_drag: Message,
|
||||
on_message: fn(ColorPickerUpdate) -> Message,
|
||||
) -> Element<Message> {
|
||||
let header = cosmic::widget::header_bar()
|
||||
.title(fl!("color-picker"))
|
||||
.on_close(on_message(ColorPickerUpdate::AppliedColor))
|
||||
.on_drag(on_drag);
|
||||
// let content = cosmic::widget::container(
|
||||
// model
|
||||
// .builder(on_message)
|
||||
// .width(Length::Fixed(254.0))
|
||||
// .height(Length::Fixed(174.0))
|
||||
// .reset_label(fl!("reset-to-default"))
|
||||
// .build(
|
||||
// fl!("recent-colors"),
|
||||
// fl!("copy-to-clipboard"),
|
||||
// fl!("copied-to-clipboard"),
|
||||
// ),
|
||||
// )
|
||||
// .width(Length::Fill)
|
||||
// .height(Length::Fill)
|
||||
// .center_x()
|
||||
// .style(cosmic::theme::style::Container::Background);
|
||||
|
||||
let content = cosmic::widget::container(
|
||||
model
|
||||
.builder(on_message)
|
||||
.width(Length::Fixed(254.0))
|
||||
.height(Length::Fixed(174.0))
|
||||
.reset_label(fl!("reset-to-default"))
|
||||
.build(
|
||||
fl!("recent-colors"),
|
||||
fl!("copy-to-clipboard"),
|
||||
fl!("copied-to-clipboard"),
|
||||
),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.center_x()
|
||||
.style(cosmic::theme::style::Container::Background);
|
||||
|
||||
cosmic::widget::column::with_capacity(2)
|
||||
.push(header)
|
||||
.push(content)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.align_items(cosmic::iced_core::Alignment::Center)
|
||||
.apply(Element::from)
|
||||
}
|
||||
// cosmic::widget::column::with_capacity(2)
|
||||
// .push(header)
|
||||
// .push(content)
|
||||
// .width(Length::Fill)
|
||||
// .height(Length::Fill)
|
||||
// .align_items(cosmic::iced_core::Alignment::Center)
|
||||
// .apply(Element::from)
|
||||
// }
|
||||
|
||||
enum DialogResponse {
|
||||
Error(String),
|
||||
|
|
|
|||
|
|
@ -1,15 +1,54 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use cosmic::iced::Length;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use cosmic::iced::{alignment, Length};
|
||||
use cosmic::iced_core::text::Wrap;
|
||||
use cosmic::prelude::CollectionWidget;
|
||||
use cosmic::widget::color_picker::ColorPickerUpdate;
|
||||
use cosmic::widget::{
|
||||
self, button, column, container, divider, horizontal_space, icon, row, settings, text,
|
||||
vertical_space,
|
||||
vertical_space, ColorPickerModel,
|
||||
};
|
||||
use cosmic::{theme, Apply, Element};
|
||||
use cosmic_settings_page as page;
|
||||
|
||||
pub fn color_picker_context_view<'a, Message: Clone + 'static>(
|
||||
description: Option<Cow<'static, str>>,
|
||||
reset: Cow<'static, str>,
|
||||
on_update: fn(ColorPickerUpdate) -> Message,
|
||||
model: &'a ColorPickerModel,
|
||||
) -> Element<'a, Message> {
|
||||
let theme = cosmic::theme::active();
|
||||
let spacing = &theme.cosmic().spacing;
|
||||
|
||||
cosmic::widget::column()
|
||||
.push_maybe(description.map(|description| text(description).width(Length::Fill)))
|
||||
.push(
|
||||
model
|
||||
.builder(on_update)
|
||||
.reset_label(reset)
|
||||
.height(Length::Fixed(158.0))
|
||||
.build(
|
||||
fl!("recent-colors"),
|
||||
fl!("copy-to-clipboard"),
|
||||
fl!("copied-to-clipboard"),
|
||||
)
|
||||
.apply(container)
|
||||
.width(Length::Fixed(248.0))
|
||||
.align_x(alignment::Horizontal::Center)
|
||||
.apply(container)
|
||||
.width(Length::Fill)
|
||||
.align_x(alignment::Horizontal::Center),
|
||||
)
|
||||
.padding(spacing.space_l)
|
||||
.align_items(cosmic::iced_core::Alignment::Center)
|
||||
.spacing(spacing.space_m)
|
||||
.width(Length::Fill)
|
||||
.apply(Element::from)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn search_header<Message>(
|
||||
pages: &page::Binder<Message>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue