Cosmic advanced text (#103)
* wip: update to use cosmic-advanced-text * use cosmic-advanced-text branch of iced * fix: line height and spacing for segmented button and update to get svg fix * fix: spin button styling & spacing * update iced to fix segmented button border radius * feat: example improvements * feat: helper for loading fonts * feat: add focus style to button * fix: slider height and iced fixed * feat: hash icon width and height * cleanup * update ci * refactor: always use lazy feature of iced * update iced * update iced * cleanup & update iced * update iced: new slider & tiny-skia quad updates * update iced: fixes for tiny-skia quad rendering with edge case border radius * re-export iced_runtime & iced_widget * merge master * udpate iced * update iced * update iced * update iced * fix: make rectangle_tracker subscription only return update if there is some * feat: derive macro for loading a cosmic-config * feat (cosmic-config): iced subscription * fix (example): update to rectangle tracker subscription * fix (cosmic-config) * refactor(cosmic-config-derive): add support for types with generic parameters * fix (cosmic-config): feature gate updates for subscription helpers * feat: support for custom & system themes + move cosmic-theme to libcosmic * feat: sorta hacky way of creating header bars for libcosmic + update iced to get support for resizable windows in iced-sctk * update iced * update and reexport sctk * fix: applet border radius * feat (cosmic-theme): add id and name methods * fix(cosmic-theme): reexport palette from cosmic-theme * fix(cosmic-config-derive): allow use with reexported cosmic-config * feat: update iced with fix and refactor applet env vars * update iced
This commit is contained in:
parent
a173794bed
commit
e056e8c830
65 changed files with 3431 additions and 405 deletions
187
cosmic-theme/src/output/gtk4_output.rs
Normal file
187
cosmic-theme/src/output/gtk4_output.rs
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
use crate::{
|
||||
model::{Accent, Container, ContainerType, Destructive, Widget},
|
||||
Hex, Theme, NAME,
|
||||
};
|
||||
use anyhow::{bail, Result};
|
||||
use palette::Srgba;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use std::{fmt, fs::File, io::prelude::*, path::PathBuf};
|
||||
|
||||
pub(crate) const CSS_DIR: &'static str = "css";
|
||||
pub(crate) const THEME_DIR: &'static str = "themes";
|
||||
|
||||
/// Trait for outputting the Theme as Gtk4CSS
|
||||
pub trait Gtk4Output {
|
||||
/// turn the theme into css
|
||||
fn as_css(&self) -> String;
|
||||
/// Serialize the theme as RON and write the CSS to the appropriate directories
|
||||
/// Should be written in the XDG data directory for cosmic-theme
|
||||
fn write(&self) -> Result<()>;
|
||||
}
|
||||
|
||||
impl<C> Gtk4Output for Theme<C>
|
||||
where
|
||||
C: Clone
|
||||
+ fmt::Debug
|
||||
+ Default
|
||||
+ Into<Hex>
|
||||
+ Into<Srgba>
|
||||
+ From<Srgba>
|
||||
+ Serialize
|
||||
+ DeserializeOwned,
|
||||
{
|
||||
fn as_css(&self) -> String {
|
||||
let Self {
|
||||
background,
|
||||
primary,
|
||||
secondary,
|
||||
accent,
|
||||
destructive,
|
||||
..
|
||||
} = self;
|
||||
let mut css = String::new();
|
||||
|
||||
css.push_str(&background.as_css());
|
||||
css.push_str(&primary.as_css());
|
||||
css.push_str(&secondary.as_css());
|
||||
css.push_str(&accent.as_css());
|
||||
css.push_str(&destructive.as_css());
|
||||
|
||||
css
|
||||
}
|
||||
|
||||
fn write(&self) -> Result<()> {
|
||||
// TODO sass -> css
|
||||
let ron_str = ron::ser::to_string_pretty(self, Default::default())?;
|
||||
let css_str = self.as_css();
|
||||
|
||||
let ron_path: PathBuf = [NAME, THEME_DIR].iter().collect();
|
||||
let css_path: PathBuf = [NAME, CSS_DIR].iter().collect();
|
||||
|
||||
let ron_dirs = xdg::BaseDirectories::with_prefix(ron_path)?;
|
||||
let css_dirs = xdg::BaseDirectories::with_prefix(css_path)?;
|
||||
|
||||
let ron_name = format!("{}.ron", &self.name);
|
||||
let css_name = format!("{}.css", &self.name);
|
||||
|
||||
if let Ok(p) = ron_dirs.place_data_file(ron_name) {
|
||||
let mut f = File::create(p)?;
|
||||
f.write_all(ron_str.as_bytes())?;
|
||||
} else {
|
||||
bail!("Failed to write RON theme.")
|
||||
}
|
||||
|
||||
if let Ok(p) = css_dirs.place_data_file(css_name) {
|
||||
let mut f = File::create(p)?;
|
||||
f.write_all(css_str.as_bytes())?;
|
||||
} else {
|
||||
bail!("Failed to write RON theme.")
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for converting theme data into gtk4 CSS
|
||||
pub trait AsGtk4Css<C>
|
||||
where
|
||||
C: Copy + Into<Srgba> + From<Srgba>,
|
||||
{
|
||||
/// function for converting theme data into gtk4 CSS
|
||||
fn as_css(&self) -> String;
|
||||
}
|
||||
|
||||
impl<C> AsGtk4Css<C> for Container<C>
|
||||
where
|
||||
C: Copy + Clone + fmt::Debug + Default + Into<Srgba> + From<Srgba> + fmt::Display,
|
||||
{
|
||||
fn as_css(&self) -> String {
|
||||
let Self {
|
||||
prefix,
|
||||
container,
|
||||
container_component,
|
||||
container_divider,
|
||||
container_fg,
|
||||
..
|
||||
} = self;
|
||||
|
||||
let prefix_lower = match prefix {
|
||||
ContainerType::Background => "background",
|
||||
ContainerType::Primary => "primary",
|
||||
ContainerType::Secondary => "secondary",
|
||||
};
|
||||
let component = widget_gtk4_css(prefix_lower, container_component);
|
||||
|
||||
format!(
|
||||
r#"
|
||||
@define-color {prefix_lower}_container #{{{container}}};
|
||||
@define-color {prefix_lower}_container_divider #{{{container_divider}}};
|
||||
@define-color {prefix_lower}_container_fg #{{{container_fg}}};
|
||||
{component}
|
||||
"#
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> AsGtk4Css<C> for Accent<C>
|
||||
where
|
||||
C: Clone + fmt::Debug + Default + Into<Srgba> + From<Srgba> + Serialize + DeserializeOwned,
|
||||
{
|
||||
fn as_css(&self) -> String {
|
||||
let Accent {
|
||||
accent,
|
||||
accent_fg,
|
||||
accent_nav_handle_fg,
|
||||
suggested,
|
||||
} = self;
|
||||
let suggested = widget_gtk4_css("suggested", suggested);
|
||||
|
||||
format!(
|
||||
r#"
|
||||
@define-color accent #{{{accent}}};
|
||||
@define-color accent_fg #{{{accent_fg}}};
|
||||
@define-color accent_nav_handle_fg #{{{accent_nav_handle_fg}}};
|
||||
{suggested}
|
||||
"#
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> AsGtk4Css<C> for Destructive<C>
|
||||
where
|
||||
C: Clone + fmt::Debug + Default + Into<Srgba> + From<Srgba> + Serialize + DeserializeOwned,
|
||||
{
|
||||
fn as_css(&self) -> String {
|
||||
let Destructive { destructive } = &self;
|
||||
widget_gtk4_css("destructive", destructive)
|
||||
}
|
||||
}
|
||||
|
||||
fn widget_gtk4_css<C: fmt::Display>(
|
||||
prefix: &str,
|
||||
Widget {
|
||||
base,
|
||||
hover,
|
||||
pressed,
|
||||
focused,
|
||||
divider,
|
||||
text,
|
||||
text_opacity_80,
|
||||
disabled,
|
||||
disabled_fg,
|
||||
}: &Widget<C>,
|
||||
) -> String {
|
||||
format!(
|
||||
r#"
|
||||
@define-color {prefix}_widget_base #{{{base}}};
|
||||
@define-color {prefix}_widget_hover #{{{hover}}};
|
||||
@define-color {prefix}_widget_pressed #{{{pressed}}};
|
||||
@define-color {prefix}_widget_focused #{{{focused}}};
|
||||
@define-color {prefix}_widget_divider #{{{divider}}};
|
||||
@define-color {prefix}_widget_fg #{{{text}}};
|
||||
@define-color {prefix}_widget_fg_opacity_80 #{{{text_opacity_80}}};
|
||||
@define-color {prefix}_widget_disabled #{{{disabled}}};
|
||||
@define-color {prefix}_widget_disabled_fg #{{{disabled_fg}}};
|
||||
"#
|
||||
)
|
||||
}
|
||||
8
cosmic-theme/src/output/mod.rs
Normal file
8
cosmic-theme/src/output/mod.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#[cfg(feature = "gtk4-theme")]
|
||||
/// Module for outputting the Cosmic gtk4 theme type as CSS
|
||||
pub mod gtk4_output;
|
||||
#[cfg(feature = "gtk4-theme")]
|
||||
pub use gtk4_output::*;
|
||||
|
||||
#[cfg(feature = "ron-serialization")]
|
||||
pub use ron::*;
|
||||
Loading…
Add table
Add a link
Reference in a new issue