use crate::color::Color;
use crate::draw_ctx::DrawCtx;
use crate::geometry::Rect;
use super::geometry::SEP_H;
#[derive(Clone)]
pub struct MenuStyle {
pub radius: f64,
pub shadow_offset: (f64, f64),
pub shadow_alpha: f32,
pub pad_x: f64,
pub icon_x: f64,
pub label_x: f64,
pub shortcut_right: f64,
}
impl Default for MenuStyle {
fn default() -> Self {
Self {
radius: 5.0,
shadow_offset: (5.0, -5.0),
shadow_alpha: 0.22,
pad_x: 8.0,
icon_x: 14.0,
label_x: 32.0,
shortcut_right: 28.0,
}
}
}
pub fn submenu_chevron_points(row: Rect) -> [(f64, f64); 3] {
let cx = row.x + row.width - 11.0;
let cy = row.y + row.height * 0.5;
let half_h = 4.0;
let arm = 3.0;
[(cx - arm, cy + half_h), (cx, cy), (cx - arm, cy - half_h)]
}
pub fn paint_check_mark(ctx: &mut dyn DrawCtx, cx: f64, cy: f64, color: Color) {
ctx.set_stroke_color(color);
ctx.set_line_width(1.6);
ctx.begin_path();
ctx.move_to(cx - 5.0, cy - 0.5);
ctx.line_to(cx - 1.5, cy - 4.0);
ctx.line_to(cx + 5.0, cy + 3.5);
ctx.stroke();
}
pub fn paint_submenu_chevron(ctx: &mut dyn DrawCtx, row: Rect, color: Color) {
let [a, b, c] = submenu_chevron_points(row);
ctx.set_stroke_color(color);
ctx.set_line_width(1.4);
ctx.begin_path();
ctx.move_to(a.0, a.1);
ctx.line_to(b.0, b.1);
ctx.line_to(c.0, c.1);
ctx.stroke();
}
pub fn paint_menu_bar_button_bg(ctx: &mut dyn DrawCtx, rect: Rect, open: bool, hovered: bool) {
if !open && !hovered {
return;
}
let v = ctx.visuals();
let bg = if open {
v.accent
} else {
v.accent.with_alpha(0.18)
};
ctx.set_fill_color(bg);
ctx.begin_path();
ctx.rounded_rect(
rect.x + 1.0,
rect.y + 2.0,
rect.width - 2.0,
rect.height - 4.0,
4.0,
);
ctx.fill();
}
pub fn bar_button_text_color(ctx: &dyn DrawCtx, open: bool) -> Color {
if open {
Color::white()
} else {
ctx.visuals().text_color
}
}
pub fn popup_row_text_color(ctx: &dyn DrawCtx, enabled: bool, open: bool) -> Color {
let v = ctx.visuals();
if !enabled {
v.text_color.with_alpha(0.45)
} else if open {
Color::white()
} else {
v.text_color
}
}
pub fn paint_panel(ctx: &mut dyn DrawCtx, rect: Rect, style: &MenuStyle) {
let v = ctx.visuals();
ctx.set_fill_color(Color::black().with_alpha(style.shadow_alpha));
ctx.begin_path();
ctx.rounded_rect(
rect.x + style.shadow_offset.0,
rect.y + style.shadow_offset.1,
rect.width,
rect.height,
style.radius,
);
ctx.fill();
ctx.set_fill_color(v.panel_fill);
ctx.begin_path();
ctx.rounded_rect(rect.x, rect.y, rect.width, rect.height, style.radius);
ctx.fill();
ctx.set_stroke_color(v.widget_stroke);
ctx.set_line_width(1.0);
ctx.begin_path();
ctx.rounded_rect(rect.x, rect.y, rect.width, rect.height, style.radius);
ctx.stroke();
}
pub fn paint_separator(ctx: &mut dyn DrawCtx, rect: Rect) {
let v = ctx.visuals();
ctx.set_stroke_color(v.widget_stroke.with_alpha(0.55));
ctx.set_line_width(1.0);
ctx.begin_path();
ctx.move_to(rect.x + 8.0, rect.y + SEP_H * 0.5);
ctx.line_to(rect.x + rect.width - 8.0, rect.y + SEP_H * 0.5);
ctx.stroke();
}
pub fn paint_item_row_bg(
ctx: &mut dyn DrawCtx,
rect: Rect,
hovered: bool,
open: bool,
enabled: bool,
) {
let hovered = hovered && enabled;
let open = open && enabled;
if !hovered && !open {
return;
}
let v = ctx.visuals();
let bg = if open {
v.accent
} else {
v.accent.with_alpha(0.18)
};
ctx.set_fill_color(bg);
ctx.begin_path();
ctx.rounded_rect(
rect.x + 3.0,
rect.y + 2.0,
rect.width - 6.0,
rect.height - 4.0,
3.0,
);
ctx.fill();
}