* feat: add support for dark / light mode switching and simultaneouscustom light / dark mode themes * refactor(color-picker): optional initial color and fallback color * refactor: used FixedPortion for layout of the settings item This makes sure that the control always has at least the specified portion of the available space * refactor: make all members of the ThemeBuilder public * refactor: add and update palette colors * fix(theme): typo and derive PartialEq for ThemeBuilder * fix: update color picker usage * feat: add more variables to the theme * fix: radius on headerbar * fix: Theme CosmicConfigEntry impl * chore: specify rev of taffy * fix: theme CosmicConfigEntry missing variables * fix: apply theme type when theme mode changes * wip: add plus icon to empty color picker button * chore: fix rev and imports * refactor(color-picker): allow custom size for the icon * refactor(color_picker): make color_button public * update iced
85 lines
2.8 KiB
Rust
85 lines
2.8 KiB
Rust
use proc_macro::TokenStream;
|
|
use quote::quote;
|
|
use syn::{self};
|
|
|
|
#[proc_macro_derive(CosmicConfigEntry)]
|
|
pub fn cosmic_config_entry_derive(input: TokenStream) -> TokenStream {
|
|
// Construct a representation of Rust code as a syntax tree
|
|
// that we can manipulate
|
|
let ast = syn::parse(input).unwrap();
|
|
|
|
// Build the trait implementation
|
|
impl_cosmic_config_entry_macro(&ast)
|
|
}
|
|
|
|
fn impl_cosmic_config_entry_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|
let name = &ast.ident;
|
|
// let generics = &ast.generics;
|
|
|
|
// Get the fields of the struct
|
|
let fields = match ast.data {
|
|
syn::Data::Struct(ref data_struct) => match data_struct.fields {
|
|
syn::Fields::Named(ref fields) => &fields.named,
|
|
_ => unimplemented!("Only named fields are supported"),
|
|
},
|
|
_ => unimplemented!("Only structs are supported"),
|
|
};
|
|
|
|
let write_each_config_field = fields.iter().map(|field| {
|
|
let field_name = &field.ident;
|
|
quote! {
|
|
cosmic_config::ConfigSet::set(config, stringify!(#field_name), &self.#field_name)?;
|
|
}
|
|
});
|
|
|
|
let get_each_config_field = fields.iter().map(|field| {
|
|
let field_name = &field.ident;
|
|
let field_type = &field.ty;
|
|
quote! {
|
|
match cosmic_config::ConfigGet::get::<#field_type>(config, stringify!(#field_name)) {
|
|
Ok(#field_name) => default.#field_name = #field_name,
|
|
Err(e) => errors.push(e),
|
|
}
|
|
}
|
|
});
|
|
|
|
// // Get the existing where clause or create a new one if it doesn't exist
|
|
// let mut where_clause = ast
|
|
// .generics
|
|
// .where_clause
|
|
// .clone()
|
|
// .unwrap_or_else(|| parse_quote!(where));
|
|
|
|
// // Add your additional constraints to the where clause
|
|
// // Here, we add the constraint 'T: Debug' to all generic parameters
|
|
// for param in ast.generics.params.iter() {
|
|
// where_clause
|
|
// .predicates
|
|
// .push(parse_quote!(#param: ::std::default::Default + ::serde::Serialize + ::serde::de::DeserializeOwned));
|
|
// }
|
|
|
|
let gen = quote! {
|
|
impl CosmicConfigEntry for #name {
|
|
fn write_entry(&self, config: &cosmic_config::Config) -> Result<(), cosmic_config::Error> {
|
|
let tx = config.transaction();
|
|
#(#write_each_config_field)*
|
|
tx.commit()
|
|
}
|
|
|
|
fn get_entry(config: &cosmic_config::Config) -> Result<Self, (Vec<cosmic_config::Error>, Self)> {
|
|
let mut default = Self::default();
|
|
let mut errors = Vec::new();
|
|
|
|
#(#get_each_config_field)*
|
|
|
|
if errors.is_empty() {
|
|
Ok(default)
|
|
} else {
|
|
Err((errors, default))
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
gen.into()
|
|
}
|