Include builtin cosmic dark and light theme in color schemes list, fixes #206

This commit is contained in:
Jeremy Soller 2024-06-05 08:51:26 -06:00
parent 69468765b7
commit c0d1ab1fb8
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
4 changed files with 180 additions and 123 deletions

3
Cargo.lock generated
View file

@ -1208,13 +1208,14 @@ dependencies = [
[[package]]
name = "cosmic-text"
version = "0.11.2"
source = "git+https://github.com/pop-os/cosmic-text.git#5e82de11cf5c977ee82a5d631c05382f4acc7314"
source = "git+https://github.com/pop-os/cosmic-text.git#89503b254fb6a2014d3712568054b32925ea9008"
dependencies = [
"bitflags 2.5.0",
"fontdb",
"libm",
"log",
"rangemap",
"rayon",
"rustc-hash",
"rustybuzz",
"self_cell 1.0.4",

View file

@ -272,9 +272,9 @@ pub enum Message {
AppTheme(AppTheme),
ColorSchemeCollapse,
ColorSchemeDelete(ColorSchemeKind, ColorSchemeId),
ColorSchemeExpand(ColorSchemeKind, ColorSchemeId),
ColorSchemeExport(ColorSchemeKind, ColorSchemeId),
ColorSchemeExportResult(ColorSchemeKind, ColorSchemeId, DialogResult),
ColorSchemeExpand(ColorSchemeKind, Option<ColorSchemeId>),
ColorSchemeExport(ColorSchemeKind, Option<ColorSchemeId>),
ColorSchemeExportResult(ColorSchemeKind, Option<ColorSchemeId>, DialogResult),
ColorSchemeImport(ColorSchemeKind),
ColorSchemeImportResult(ColorSchemeKind, DialogResult),
ColorSchemeRename(ColorSchemeKind, ColorSchemeId, String),
@ -401,7 +401,7 @@ pub struct App {
startup_options: Option<tty::Options>,
term_config: term::Config,
color_scheme_errors: Vec<String>,
color_scheme_expanded: Option<(ColorSchemeKind, ColorSchemeId)>,
color_scheme_expanded: Option<(ColorSchemeKind, Option<ColorSchemeId>)>,
color_scheme_renaming: Option<(ColorSchemeKind, ColorSchemeId, String)>,
color_scheme_rename_id: widget::Id,
color_scheme_tab_model: widget::segmented_button::SingleSelectModel,
@ -696,65 +696,67 @@ impl App {
.into(),
);
if !self.config.color_schemes(color_scheme_kind).is_empty() {
let mut section = widget::settings::view_section("");
for (color_scheme_name, color_scheme_id) in
self.config.color_scheme_names(color_scheme_kind)
{
let expanded =
self.color_scheme_expanded == Some((color_scheme_kind, color_scheme_id));
let renaming = match &self.color_scheme_renaming {
Some((kind, id, value))
if kind == &color_scheme_kind && id == &color_scheme_id =>
{
Some(value)
}
_ => None,
};
let button = if expanded {
widget::button(icon_cache_get("view-more-symbolic", 16))
.on_press(Message::ColorSchemeCollapse)
} else {
widget::button(icon_cache_get("view-more-symbolic", 16)).on_press(
Message::ColorSchemeExpand(color_scheme_kind, color_scheme_id),
)
let mut section = widget::settings::view_section("");
let builtin_name = format!("COSMIC {:?}", color_scheme_kind);
let color_scheme_names = self.config.color_scheme_names(color_scheme_kind);
for (color_scheme_name, color_scheme_id_opt) in std::iter::once((builtin_name, None)).chain(
color_scheme_names
.into_iter()
.map(|(name, id)| (name, Some(id))),
) {
let expanded =
self.color_scheme_expanded == Some((color_scheme_kind, color_scheme_id_opt));
let renaming = match &self.color_scheme_renaming {
Some((kind, id, value))
if kind == &color_scheme_kind && Some(id) == color_scheme_id_opt.as_ref() =>
{
Some(value)
}
.style(style::Button::Icon);
_ => None,
};
let mut popover = widget::popover(button);
if expanded {
let menu = menu::color_scheme_menu(
color_scheme_kind,
color_scheme_id,
&color_scheme_name,
);
popover = popover
.popup(menu)
.position(widget::popover::Position::Bottom);
}
let item = match renaming {
Some(value) => widget::settings::item_row(vec![
widget::text_input("", value)
.id(self.color_scheme_rename_id.clone())
.on_input(move |value| {
Message::ColorSchemeRename(
color_scheme_kind,
color_scheme_id,
value,
)
})
.on_submit(Message::ColorSchemeRenameSubmit)
.into(),
popover.into(),
]),
None => widget::settings::item::builder(color_scheme_name).control(popover),
};
section = section.add(item);
let button = if expanded {
widget::button(icon_cache_get("view-more-symbolic", 16))
.on_press(Message::ColorSchemeCollapse)
} else {
widget::button(icon_cache_get("view-more-symbolic", 16)).on_press(
Message::ColorSchemeExpand(color_scheme_kind, color_scheme_id_opt),
)
}
sections.push(section.into());
.style(style::Button::Icon);
let mut popover = widget::popover(button);
if expanded {
let menu = menu::color_scheme_menu(
color_scheme_kind,
color_scheme_id_opt,
&color_scheme_name,
);
popover = popover
.popup(menu)
.position(widget::popover::Position::Bottom);
}
let item = match renaming {
Some(value) => widget::settings::item_row(vec![
widget::text_input("", value)
.id(self.color_scheme_rename_id.clone())
.on_input(move |value| {
Message::ColorSchemeRename(
color_scheme_kind,
color_scheme_id_opt.expect("trying to rename builtin color scheme"),
value,
)
})
.on_submit(Message::ColorSchemeRenameSubmit)
.into(),
popover.into(),
]),
None => widget::settings::item::builder(color_scheme_name).control(popover),
};
section = section.add(item);
}
sections.push(section.into());
sections.push(
widget::row::with_children(vec![
@ -1520,24 +1522,27 @@ impl Application for App {
.remove(&color_scheme_id);
return self.save_color_schemes(color_scheme_kind);
}
Message::ColorSchemeExport(color_scheme_kind, color_scheme_id) => {
Message::ColorSchemeExport(color_scheme_kind, color_scheme_id_opt) => {
self.color_scheme_expanded = None;
if let Some(color_scheme) = self
.config
.color_schemes(color_scheme_kind)
.get(&color_scheme_id)
{
if let Some(color_scheme_name) = match color_scheme_id_opt {
Some(color_scheme_id) => self
.config
.color_schemes(color_scheme_kind)
.get(&color_scheme_id)
.map(|color_scheme| color_scheme.name.clone()),
None => Some(format!("COSMIC {:?}", color_scheme_kind)),
} {
if self.dialog_opt.is_none() {
let (dialog, command) = Dialog::new(
DialogKind::SaveFile {
filename: format!("{}.ron", color_scheme.name),
filename: format!("{}.ron", color_scheme_name),
},
None,
Message::DialogMessage,
move |result| {
Message::ColorSchemeExportResult(
color_scheme_kind,
color_scheme_id,
color_scheme_id_opt,
result,
)
},
@ -1547,45 +1552,85 @@ impl Application for App {
}
}
}
Message::ColorSchemeExportResult(color_scheme_kind, color_scheme_id, result) => {
Message::ColorSchemeExportResult(color_scheme_kind, color_scheme_id_opt, result) => {
//TODO: show errors in UI
self.dialog_opt = None;
if let DialogResult::Open(paths) = result {
let path = &paths[0];
if let Some(color_scheme) = self
.config
.color_schemes(color_scheme_kind)
.get(&color_scheme_id)
{
match ron::ser::to_string_pretty(
&color_scheme,
ron::ser::PrettyConfig::new(),
) {
Ok(ron) => {
if let Err(err) = fs::write(path, ron) {
match color_scheme_id_opt {
Some(color_scheme_id) => {
if let Some(color_scheme) = self
.config
.color_schemes(color_scheme_kind)
.get(&color_scheme_id)
{
match ron::ser::to_string_pretty(
&color_scheme,
ron::ser::PrettyConfig::new(),
) {
Ok(ron) => {
if let Err(err) = fs::write(path, ron) {
log::error!(
"failed to export {:?} to {:?}: {}",
color_scheme_id,
path,
err
);
}
}
Err(err) => {
log::error!(
"failed to serialize color scheme {:?}: {}",
color_scheme_id,
err
);
}
}
} else {
log::error!("failed to find color scheme {:?}", color_scheme_id);
}
}
None => {
let name = format!("COSMIC {:?}", color_scheme_kind);
let color_scheme = match color_scheme_kind {
ColorSchemeKind::Dark => ColorScheme::from((
name.as_str(),
&terminal_theme::cosmic_dark(),
)),
ColorSchemeKind::Light => ColorScheme::from((
name.as_str(),
&terminal_theme::cosmic_light(),
)),
};
//TODO: do not duplicate code
match ron::ser::to_string_pretty(
&color_scheme,
ron::ser::PrettyConfig::new(),
) {
Ok(ron) => {
if let Err(err) = fs::write(path, ron) {
log::error!(
"failed to export {:?} to {:?}: {}",
color_scheme.name,
path,
err
);
}
}
Err(err) => {
log::error!(
"failed to export {:?} to {:?}: {}",
color_scheme_id,
path,
"failed to serialize color scheme {:?}: {}",
color_scheme.name,
err
);
}
}
Err(err) => {
log::error!(
"failed to serialize color scheme {:?}: {}",
color_scheme_id,
err
);
}
}
} else {
log::error!("failed to find color scheme {:?}", color_scheme_id);
}
}
}
Message::ColorSchemeExpand(color_scheme_kind, color_scheme_id) => {
self.color_scheme_expanded = Some((color_scheme_kind, color_scheme_id));
Message::ColorSchemeExpand(color_scheme_kind, color_scheme_id_opt) => {
self.color_scheme_expanded = Some((color_scheme_kind, color_scheme_id_opt));
}
Message::ColorSchemeImport(color_scheme_kind) => {
if self.dialog_opt.is_none() {

View file

@ -97,39 +97,50 @@ pub fn context_menu<'a>(
pub fn color_scheme_menu<'a>(
kind: ColorSchemeKind,
id: ColorSchemeId,
id_opt: Option<ColorSchemeId>,
name: &str,
) -> Element<'a, Message> {
let menu_item =
|label, message| menu_button(vec![widget::text(label).into()]).on_press(message);
widget::container(column!(
menu_item(
let mut column = widget::column::with_capacity(if id_opt.is_some() { 3 } else { 1 });
if let Some(id) = id_opt {
column = column.push(menu_item(
fl!("rename"),
Message::ColorSchemeRename(kind, id, name.to_string())
),
menu_item(fl!("export"), Message::ColorSchemeExport(kind, id)),
menu_item(fl!("delete"), Message::ColorSchemeDelete(kind, id)),
))
.padding(1)
//TODO: move style to libcosmic
.style(theme::Container::custom(|theme| {
let cosmic = theme.cosmic();
let component = &cosmic.background.component;
widget::container::Appearance {
icon_color: Some(component.on.into()),
text_color: Some(component.on.into()),
background: Some(Background::Color(component.base.into())),
border: Border {
radius: 8.0.into(),
width: 1.0,
color: component.divider.into(),
},
..Default::default()
}
}))
.width(Length::Fixed(120.0))
.into()
Message::ColorSchemeRename(kind, id, name.to_string()),
));
}
column = column.push(menu_item(
fl!("export"),
Message::ColorSchemeExport(kind, id_opt),
));
if let Some(id) = id_opt {
column = column.push(menu_item(
fl!("delete"),
Message::ColorSchemeDelete(kind, id),
));
}
widget::container(column)
.padding(1)
//TODO: move style to libcosmic
.style(theme::Container::custom(|theme| {
let cosmic = theme.cosmic();
let component = &cosmic.background.component;
widget::container::Appearance {
icon_color: Some(component.on.into()),
text_color: Some(component.on.into()),
background: Some(Background::Color(component.base.into())),
border: Border {
radius: 8.0.into(),
width: 1.0,
color: component.divider.into(),
},
..Default::default()
}
}))
.width(Length::Fixed(120.0))
.into()
}
pub fn menu_bar<'a>(config: &Config, key_binds: &HashMap<KeyBind, Action>) -> Element<'a, Message> {

View file

@ -248,7 +248,7 @@ impl From<(&str, &Colors)> for ColorScheme {
}
}
fn cosmic_dark() -> Colors {
pub fn cosmic_dark() -> Colors {
let mut colors = auto_colors();
let encode_rgb = |data: u32| -> Rgb {
@ -289,7 +289,7 @@ fn cosmic_dark() -> Colors {
colors
}
fn cosmic_light() -> Colors {
pub fn cosmic_light() -> Colors {
let mut colors = auto_colors();
let encode_rgb = |data: u32| -> Rgb {