From c14cd1096ec8883b541ca7573fd8999ccf715831 Mon Sep 17 00:00:00 2001 From: Jacobsky Date: Sat, 4 Jun 2022 13:36:07 +0900 Subject: [PATCH] Fixed issue where text_styles were not being serialized correctly. Added error message to the serialization macro so that when properties there will be at least some output. --- egui-theme/src/tests/ser.rs | 57 ++++++++++++++++++++++++++++++++++- egui-theme/src/theme/fonts.rs | 2 -- egui-theme/src/theme/style.rs | 39 +++++++++++++++++++----- 3 files changed, 88 insertions(+), 10 deletions(-) diff --git a/egui-theme/src/tests/ser.rs b/egui-theme/src/tests/ser.rs index 3c8533d..893595c 100644 --- a/egui-theme/src/tests/ser.rs +++ b/egui-theme/src/tests/ser.rs @@ -1,4 +1,4 @@ -use egui::FontData; +use egui::{Style, TextStyle, FontId, FontFamily, FontData, FontDefinitions}; use crate::EguiTheme; #[test] @@ -132,3 +132,58 @@ fn test_custom_font_serialization() { "Nacelle data does not exist in the serialized string" ); } + +#[test] +fn test_text_style() { + let mut style = Style::default(); + let mut fonts = FontDefinitions::default(); + + const FONT_NAME: &str = "NacelleFontData"; + fonts.font_data.insert( + FONT_NAME.to_owned(), + FontData::from_static(include_bytes!("test-fonts/Nacelle-Regular.otf")), + ); + fonts.families.insert( + egui::FontFamily::Name(FONT_NAME.into()), + vec![FONT_NAME.to_owned()], + ); + + fonts.families.insert(FontFamily::Name("NacelleFontFamily".into()), vec![FONT_NAME.to_owned()]); + style.text_styles.insert(TextStyle::Name("NacelleStyle".into()), FontId::new(12.0, FontFamily::Name("NacelleFontFamily".into()))); + + let theme = EguiTheme::new(style, fonts); + let serialized = serde_json::to_string(&theme).expect("serialization failed"); + assert!(serialized.contains("NacelleFontData"), "Nacelle Font Data was not serialized correctly"); + assert!(serialized.contains("NacelleFontFamily"), "FontFamily was not serialized correctly"); + assert!(serialized.contains("NacelleStyle"), "TextStyle was not serialized correctly"); + + let deserialized = serde_json::from_str::(serialized.as_str()).expect("deserialization failed"); + let (de_style, _fonts) = deserialized.extract(); + assert!(de_style.text_styles().contains(&TextStyle::Body), "text style `Body` does not exist"); + assert!(de_style.text_styles().contains(&TextStyle::Small), "text style `Small` does not exist"); + assert!(de_style.text_styles().contains(&TextStyle::Monospace), "text style `Monospace` does not exist"); + assert!(de_style.text_styles().contains(&TextStyle::Button), "text style `Button` does not exist"); + assert!(de_style.text_styles().contains(&TextStyle::Heading), "text style `Heading` does not exist"); + assert!(de_style.text_styles().contains(&TextStyle::Name("NacelleStyle".into())), "text style `NacelleStyle` does not exist"); + assert!(de_style.text_styles.get(&TextStyle::Name("NacelleStyle".into())).is_some(), "could not get the text_style"); + assert_eq!(*de_style.text_styles.get(&TextStyle::Name("NacelleStyle".into())).unwrap(), FontId::new(12.0, FontFamily::Name("NacelleFontFamily".into())), "FontStyle not deserialized"); +} +#[test] +fn test_colors() { + let mut style = Style::default(); + let fg_stroke = egui::Stroke::new(1f32, egui::Color32::TRANSPARENT); + style.visuals.widgets.noninteractive.fg_stroke = fg_stroke.clone(); + style.visuals.widgets.inactive.bg_fill = egui::Color32::LIGHT_RED; + + let theme = EguiTheme::new(style, FontDefinitions::default()); + let serialized = serde_json::to_string(&theme).expect("serialization failed"); + let deserialized = serde_json::from_str::(serialized.as_str()).expect("deserialization failed"); + let (de_style, _fonts) = deserialized.extract(); + + assert_eq!( + de_style.visuals.widgets.noninteractive.fg_stroke, fg_stroke.clone(), "stroke doesn't match" + ); + assert_eq!( + de_style.visuals.widgets.inactive.bg_fill, egui::Color32::LIGHT_RED, "Color doesn't match" + ); +} \ No newline at end of file diff --git a/egui-theme/src/theme/fonts.rs b/egui-theme/src/theme/fonts.rs index f19ed41..ab6e902 100644 --- a/egui-theme/src/theme/fonts.rs +++ b/egui-theme/src/theme/fonts.rs @@ -27,7 +27,6 @@ pub fn from_fonts( serde_json::to_value(font_data).expect("serialization error occurred"), ); - println!("{:?}", &families); // Workaround due to FontFamily not properly serializing to "String" when attempting to serialize the BTreeMap> let families = { families @@ -45,7 +44,6 @@ pub fn from_fonts( serde_json::to_value(families).expect("serialization error occurred"), ); - println!("{:?}", hash_map.get(FAMILIES_KEY)); hash_map } diff --git a/egui-theme/src/theme/style.rs b/egui-theme/src/theme/style.rs index 9321548..b12215b 100644 --- a/egui-theme/src/theme/style.rs +++ b/egui-theme/src/theme/style.rs @@ -1,15 +1,19 @@ use egui::Style; use std::collections::HashMap; +const TEXT_STYLES_KEY: &str = "text_styles"; + macro_rules! ser { ($collection:ident, $style:ident, $prop:ident) => { - if let Ok(value) = serde_json::to_value($style.$prop.to_owned()) { - $collection.insert(stringify!($prop).to_owned(), value); - } + match serde_json::to_value($style.$prop.to_owned()) { + Ok(value) => { let _ = $collection.insert(stringify!($prop).to_owned(), value); }, + Err(error) => { println!("{}", error); }, + } }; ($collection:ident, $style:ident, $prop:ident, $sub_prop:ident) => { - if let Ok(value) = serde_json::to_value($style.$prop.$sub_prop.to_owned()) { - $collection.insert(stringify!($prop.$sub_prop).to_owned(), value); + match serde_json::to_value($style.$prop.$sub_prop.to_owned()) { + Ok(value) => { let _ = $collection.insert(stringify!($prop.$sub_prop).to_owned(), value); }, + Err(error) => { println!("{}", error); }, } }; } @@ -37,11 +41,22 @@ macro_rules! de { pub fn from_style(style: Style) -> HashMap { let mut hash_map = HashMap::new(); + { + let text_styles = style.text_styles.iter() + .map(|(k, v)| (k.to_owned(), v.to_owned() )) + .collect::>(); + if let Ok(value) = serde_json::to_value(text_styles) { + hash_map.insert(TEXT_STYLES_KEY.to_owned(), value); + } + } + // Text Styles are a special case due to being a map that must serialize to a string. + // ser!(hash_map, style, text_styles); + ser!(hash_map, style, override_text_style); ser!(hash_map, style, override_font_id); - ser!(hash_map, style, text_styles); ser!(hash_map, style, wrap); + ser!(hash_map, style, animation_time); ser!(hash_map, style, explanation_tooltips); @@ -86,10 +101,19 @@ pub fn from_style(style: Style) -> HashMap { /// Helper function to deserialize the `egui::Style` pub fn to_style(hash_map: HashMap) -> Style { let mut style = Style::default(); + // Special case due to json requiring String keys + { + hash_map.get(TEXT_STYLES_KEY).map(|value| { + if let Ok(values) = serde_json::from_value::>(value.to_owned()) { + for (key, value) in values { + style.text_styles.insert(key, value); + } + } + }); + } de!(hash_map, style, override_text_style); de!(hash_map, style, override_font_id); - de!(hash_map, style, text_styles); de!(hash_map, style, wrap); de!(hash_map, style, animation_time); @@ -112,6 +136,7 @@ pub fn to_style(hash_map: HashMap) -> Style { de!(hash_map, style, interaction, resize_grab_radius_side); de!(hash_map, style, interaction, resize_grab_radius_corner); de!(hash_map, style, interaction, show_tooltips_only_when_still); + de!(hash_map, style, visuals, dark_mode); de!(hash_map, style, visuals, override_text_color); de!(hash_map, style, visuals, widgets);