use crate::color::Color;
use crate::draw_ctx::DrawCtx;
use crate::theme::Visuals;
#[derive(Clone, Debug)]
pub struct ChromeStyle {
pub corner_radius: f64,
pub title_height: f64,
pub shadow_blur: f64,
pub shadow_dx: f64,
pub shadow_dy: f64,
pub shadow_steps: usize,
pub shadow_color: Color,
pub body_color: Color,
pub border_color: Color,
pub title_color: Color,
pub title_text_color: Color,
pub separator_color: Color,
}
impl ChromeStyle {
pub fn from_visuals(v: &Visuals) -> Self {
Self {
corner_radius: 8.0,
title_height: 28.0,
shadow_blur: 14.0,
shadow_dx: 2.0,
shadow_dy: 6.0,
shadow_steps: 10,
shadow_color: v.window_shadow,
body_color: v.window_fill,
border_color: v.window_stroke,
title_color: v.window_title_fill,
title_text_color: v.window_title_text,
separator_color: v.window_stroke,
}
}
}
pub fn paint_chrome_shadow(ctx: &mut dyn DrawCtx, w: f64, h: f64, style: &ChromeStyle) {
let base = style.shadow_color;
let steps = style.shadow_steps.max(1);
for i in (0..steps).rev() {
let t = i as f64 / steps as f64;
let infl = t * style.shadow_blur;
let falloff = (1.0 - t).powi(2) as f32;
let alpha = base.a * falloff / steps as f32 * 6.0;
ctx.set_fill_color(Color::rgba(base.r, base.g, base.b, alpha));
ctx.begin_path();
ctx.rounded_rect(
style.shadow_dx - infl,
-style.shadow_dy - infl,
w + 2.0 * infl,
h + 2.0 * infl,
style.corner_radius + infl,
);
ctx.fill();
}
}
pub fn paint_chrome_body(
ctx: &mut dyn DrawCtx,
w: f64,
h: f64,
style: &ChromeStyle,
collapsed: bool,
) {
if collapsed {
return;
}
let content_h = (h - style.title_height).max(0.0);
if content_h <= 0.0 {
return;
}
let r = style.corner_radius;
ctx.set_fill_color(style.body_color);
ctx.begin_path();
ctx.rounded_rect(0.0, 0.0, w, content_h, r);
ctx.rect(0.0, (content_h - r).max(0.0), w, r.min(content_h));
ctx.fill();
}
pub fn paint_chrome_title_bar(
ctx: &mut dyn DrawCtx,
bar_x: f64,
bar_y: f64,
w: f64,
style: &ChromeStyle,
collapsed: bool,
title: &str,
font_size: f64,
) {
let r = style.corner_radius;
let h = style.title_height;
ctx.set_fill_color(style.title_color);
ctx.begin_path();
ctx.rounded_rect(bar_x, bar_y, w, h, r);
if !collapsed {
ctx.rect(bar_x, bar_y, w, r.min(h));
}
ctx.fill();
if !collapsed {
ctx.set_fill_color(style.separator_color);
ctx.begin_path();
ctx.rect(bar_x, bar_y, w, 1.0);
ctx.fill();
}
if !title.is_empty() {
ctx.set_fill_color(style.title_text_color);
ctx.set_font_size(font_size);
ctx.fill_text(title, bar_x + 24.0, bar_y + h * 0.5 - 4.0);
}
}
pub fn paint_chrome_border(ctx: &mut dyn DrawCtx, w: f64, h: f64, style: &ChromeStyle) {
ctx.set_stroke_color(style.border_color);
ctx.set_line_width(1.0);
ctx.begin_path();
ctx.rounded_rect(
0.5,
0.5,
(w - 1.0).max(0.0),
(h - 1.0).max(0.0),
style.corner_radius,
);
ctx.stroke();
}
pub fn paint_chevron(ctx: &mut dyn DrawCtx, cx: f64, cy: f64, collapsed: bool, color: Color) {
let sz = 4.0;
ctx.set_stroke_color(color);
ctx.set_line_width(1.5);
ctx.begin_path();
if collapsed {
ctx.move_to(cx, cy - sz);
ctx.line_to(cx + sz, cy);
ctx.line_to(cx, cy + sz);
} else {
ctx.move_to(cx - sz, cy + sz * 0.5);
ctx.line_to(cx, cy - sz * 0.5);
ctx.line_to(cx + sz, cy + sz * 0.5);
}
ctx.stroke();
}