use crate::core::guide::LegendPosition;
use crate::prelude::SingleColor;
use crate::visual::color::{ColorMap, ColorPalette};
#[derive(Clone)]
pub struct Theme {
pub(crate) background_color: SingleColor,
pub(crate) top_margin: f64,
pub(crate) right_margin: f64,
pub(crate) bottom_margin: f64,
pub(crate) left_margin: f64,
pub(crate) show_axes: bool,
pub(crate) title_size: f64,
pub(crate) title_family: String,
pub(crate) title_color: SingleColor,
pub(crate) label_size: f64,
pub(crate) label_family: String,
pub(crate) label_color: SingleColor,
pub(crate) label_padding: f64,
pub(crate) tick_label_size: f64,
pub(crate) tick_label_family: String,
pub(crate) tick_label_color: SingleColor,
pub(crate) tick_label_padding: f64,
pub(crate) x_tick_label_angle: f64,
pub(crate) y_tick_label_angle: f64,
pub(crate) axis_width: f64,
pub(crate) tick_width: f64,
pub(crate) tick_length: f64,
pub(crate) tick_min_spacing: f64,
pub(crate) legend_title_size: f64,
pub(crate) legend_label_size: f64,
pub(crate) legend_label_family: String,
pub(crate) legend_label_color: SingleColor,
pub(crate) legend_position: LegendPosition,
pub(crate) legend_margin: f64,
pub(crate) legend_block_gap: f64,
pub(crate) legend_item_v_gap: f64,
pub(crate) legend_col_h_gap: f64,
pub(crate) legend_title_gap: f64,
pub(crate) legend_marker_text_gap: f64,
pub(crate) min_panel_size: f64,
pub(crate) panel_defense_ratio: f64,
pub(crate) axis_reserve_buffer: f64,
pub(crate) color_map: ColorMap,
pub(crate) palette: ColorPalette,
pub(crate) facet_label_size: f64,
pub(crate) facet_label_color: SingleColor,
pub(crate) facet_strip_fill: SingleColor,
pub(crate) facet_spacing: f64,
pub(crate) facet_strip_padding: f64,
pub(crate) polar_start_angle: f64,
pub(crate) polar_end_angle: f64,
pub(crate) polar_inner_radius: f64,
pub(crate) grid_color: SingleColor,
pub(crate) grid_width: f64,
}
impl Theme {
pub fn with_background_color(mut self, color: impl Into<SingleColor>) -> Self {
self.background_color = color.into();
self
}
pub fn with_top_margin(mut self, margin: f64) -> Self {
self.top_margin = margin;
self
}
pub fn with_right_margin(mut self, margin: f64) -> Self {
self.right_margin = margin;
self
}
pub fn with_bottom_margin(mut self, margin: f64) -> Self {
self.bottom_margin = margin;
self
}
pub fn with_left_margin(mut self, margin: f64) -> Self {
self.top_margin = margin;
self
}
pub fn with_show_axes(mut self, show: bool) -> Self {
self.show_axes = show;
self
}
pub fn with_title_size(mut self, size: f64) -> Self {
self.title_size = size;
self
}
pub fn with_title_family(mut self, family: impl Into<String>) -> Self {
self.title_family = family.into();
self
}
pub fn with_title_color(mut self, color: impl Into<SingleColor>) -> Self {
self.title_color = color.into();
self
}
pub fn with_label_size(mut self, size: f64) -> Self {
self.label_size = size;
self
}
pub fn with_label_family(mut self, family: impl Into<String>) -> Self {
self.label_family = family.into();
self
}
pub fn with_label_color(mut self, color: impl Into<SingleColor>) -> Self {
self.label_color = color.into();
self
}
pub fn with_label_padding(mut self, padding: f64) -> Self {
self.label_padding = padding;
self
}
pub fn with_tick_label_size(mut self, size: f64) -> Self {
self.tick_label_size = size;
self
}
pub fn with_tick_label_family(mut self, family: impl Into<String>) -> Self {
self.tick_label_family = family.into();
self
}
pub fn with_tick_label_color(mut self, color: impl Into<SingleColor>) -> Self {
self.tick_label_color = color.into();
self
}
pub fn with_tick_label_padding(mut self, padding: f64) -> Self {
self.tick_label_padding = padding;
self
}
pub fn with_x_tick_label_angle(mut self, angle: f64) -> Self {
self.x_tick_label_angle = angle;
self
}
pub fn with_y_tick_label_angle(mut self, angle: f64) -> Self {
self.y_tick_label_angle = angle;
self
}
pub fn with_axis_width(mut self, width: f64) -> Self {
self.axis_width = width;
self
}
pub fn with_tick_width(mut self, width: f64) -> Self {
self.tick_width = width;
self
}
pub fn with_tick_length(mut self, length: f64) -> Self {
self.tick_length = length;
self
}
pub fn with_tick_min_spacing(mut self, spacing: f64) -> Self {
self.tick_min_spacing = spacing;
self
}
pub fn with_legend_title_size(mut self, size: f64) -> Self {
self.legend_title_size = size;
self
}
pub fn with_legend_label_size(mut self, size: f64) -> Self {
self.legend_label_size = size;
self
}
pub fn with_legend_label_family(mut self, family: impl Into<String>) -> Self {
self.legend_label_family = family.into();
self
}
pub fn with_legend_label_color(mut self, color: impl Into<SingleColor>) -> Self {
self.legend_label_color = color.into();
self
}
pub fn with_legend_block_gap(mut self, gap: f64) -> Self {
self.legend_block_gap = gap;
self
}
pub fn with_legend_item_v_gap(mut self, gap: f64) -> Self {
self.legend_item_v_gap = gap;
self
}
pub fn with_legend_col_h_gap(mut self, gap: f64) -> Self {
self.legend_col_h_gap = gap;
self
}
pub fn with_legend_title_gap(mut self, gap: f64) -> Self {
self.legend_title_gap = gap;
self
}
pub fn with_legend_marker_text_gap(mut self, gap: f64) -> Self {
self.legend_marker_text_gap = gap;
self
}
pub fn with_legend_position(mut self, position: LegendPosition) -> Self {
self.legend_position = position;
self
}
pub fn with_legend_margin(mut self, margin: f64) -> Self {
self.legend_margin = margin;
self
}
pub fn with_min_panel_size(mut self, size: f64) -> Self {
self.min_panel_size = size;
self
}
pub fn with_panel_defense_ratio(mut self, ratio: f64) -> Self {
self.panel_defense_ratio = ratio;
self
}
pub fn with_axis_reserve_buffer(mut self, buffer: f64) -> Self {
self.axis_reserve_buffer = buffer;
self
}
pub fn with_color_map(mut self, map: ColorMap) -> Self {
self.color_map = map;
self
}
pub fn with_palette(mut self, palette: ColorPalette) -> Self {
self.palette = palette;
self
}
pub fn with_facet_label_size(mut self, size: f64) -> Self {
self.facet_label_size = size;
self
}
pub fn with_facet_label_color(mut self, color: impl Into<SingleColor>) -> Self {
self.facet_label_color = color.into();
self
}
pub fn with_facet_strip_fill(mut self, color: impl Into<SingleColor>) -> Self {
self.facet_strip_fill = color.into();
self
}
pub fn with_facet_spacing(mut self, spacing: f64) -> Self {
self.facet_spacing = spacing;
self
}
pub fn with_facet_strip_padding(mut self, padding: f64) -> Self {
self.facet_strip_padding = padding;
self
}
pub fn suggest_tick_count(&self, available_pixels: f64) -> usize {
((available_pixels / self.tick_min_spacing).floor() as usize).max(2)
}
pub fn with_grid_color(mut self, color: impl Into<SingleColor>) -> Self {
self.grid_color = color.into();
self
}
pub fn with_grid_width(mut self, width: f64) -> Self {
self.grid_width = width;
self
}
}
impl Default for Theme {
fn default() -> Self {
let font_stack = "Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, 'PingFang SC', 'Microsoft YaHei', Ubuntu, Cantarell, 'Noto Sans', sans-serif".to_string();
Self {
background_color: "white".into(),
top_margin: 0.10,
right_margin: 0.03,
bottom_margin: 0.08,
left_margin: 0.06,
show_axes: true,
title_size: 18.0,
title_family: font_stack.clone(),
title_color: "#333".into(),
label_size: 15.0,
label_family: font_stack.clone(),
label_color: "#333".into(),
label_padding: 5.0,
tick_label_size: 13.0,
tick_label_family: font_stack.clone(),
tick_label_color: "#333".into(),
tick_label_padding: 3.0,
x_tick_label_angle: 0.0,
y_tick_label_angle: 0.0,
axis_width: 1.0,
tick_width: 1.0,
tick_length: 6.0,
tick_min_spacing: 50.0,
legend_title_size: 14.0,
legend_label_size: 12.0,
legend_label_family: font_stack,
legend_label_color: "#333".into(),
legend_block_gap: 35.0,
legend_item_v_gap: 3.0,
legend_col_h_gap: 15.0,
legend_title_gap: 7.0,
legend_marker_text_gap: 8.0,
legend_position: LegendPosition::Right,
legend_margin: 15.0,
min_panel_size: 100.0,
panel_defense_ratio: 0.2,
axis_reserve_buffer: 60.0,
color_map: ColorMap::Viridis,
palette: ColorPalette::Tab10,
facet_label_size: 11.0,
facet_label_color: "#333".into(),
facet_strip_fill: "lightgray".into(),
facet_spacing: 10.0,
facet_strip_padding: 5.0,
polar_start_angle: -std::f64::consts::FRAC_PI_2,
polar_end_angle: 3.0 * std::f64::consts::FRAC_PI_2, polar_inner_radius: 0.0,
grid_color: " #BDBDBD".into(),
grid_width: 1.0,
}
}
}