use crate::render::{RenderContext, TextAlign, TextBaseline};
use crate::types::Rect;
use super::settings::ChevronSettings;
use super::types::{ChevronDirection, ChevronView, ChevronVisualKind};
pub fn draw_chevron(
ctx: &mut dyn RenderContext,
rect: Rect,
view: &ChevronView,
settings: &ChevronSettings,
) {
if !view.should_render() {
return;
}
if rect.width <= 0.0 || rect.height <= 0.0 {
return;
}
let theme = settings.theme.as_ref();
let style = settings.style.as_ref();
let color = if view.disabled {
theme.color_disabled()
} else if view.pressed {
theme.color_pressed()
} else if view.active {
theme.color_active()
} else if view.hovered {
theme.color_hover()
} else {
theme.color()
};
let interactive = !matches!(
view.use_case,
super::types::ChevronUseCase::Affordance | super::types::ChevronUseCase::IconGlyph
);
if interactive && view.hovered && !view.disabled {
ctx.set_fill_color(theme.bg_hover());
ctx.fill_rounded_rect(rect.x, rect.y, rect.width, rect.height, style.hover_bg_radius());
}
match view.visual_kind {
ChevronVisualKind::Stroked => draw_stroked(ctx, rect, view.direction, color, style),
ChevronVisualKind::Filled => draw_filled(ctx, rect, view.direction, color, style),
ChevronVisualKind::Glyph => draw_glyph(ctx, rect, view, color, style),
ChevronVisualKind::Icon => {
}
}
}
fn draw_stroked(
ctx: &mut dyn RenderContext,
rect: Rect,
direction: ChevronDirection,
color: &str,
style: &dyn super::style::ChevronStyle,
) {
let cx = rect.center_x();
let cy = rect.center_y();
let half = (style.size() / 2.0)
.min(rect.width / 2.0)
.min(rect.height / 2.0)
.max(2.0);
ctx.set_stroke_color(color);
ctx.set_stroke_width(style.thickness());
ctx.set_line_dash(&[]);
ctx.begin_path();
match direction {
ChevronDirection::Left => {
ctx.move_to(cx + half * 0.5, cy - half);
ctx.line_to(cx - half * 0.5, cy);
ctx.line_to(cx + half * 0.5, cy + half);
}
ChevronDirection::Right => {
ctx.move_to(cx - half * 0.5, cy - half);
ctx.line_to(cx + half * 0.5, cy);
ctx.line_to(cx - half * 0.5, cy + half);
}
ChevronDirection::Up => {
ctx.move_to(cx - half, cy + half * 0.5);
ctx.line_to(cx, cy - half * 0.5);
ctx.line_to(cx + half, cy + half * 0.5);
}
ChevronDirection::Down => {
ctx.move_to(cx - half, cy - half * 0.5);
ctx.line_to(cx, cy + half * 0.5);
ctx.line_to(cx + half, cy - half * 0.5);
}
}
ctx.stroke();
}
fn draw_filled(
ctx: &mut dyn RenderContext,
rect: Rect,
direction: ChevronDirection,
color: &str,
style: &dyn super::style::ChevronStyle,
) {
let s = style.triangle_size();
let cx = rect.center_x();
let cy = rect.center_y();
let hb = s / 2.0; let ah = s / 2.0;
ctx.set_fill_color(color);
ctx.begin_path();
match direction {
ChevronDirection::Down => {
ctx.move_to(cx - hb, cy - ah);
ctx.line_to(cx + hb, cy - ah);
ctx.line_to(cx, cy + ah);
}
ChevronDirection::Up => {
ctx.move_to(cx - hb, cy + ah);
ctx.line_to(cx + hb, cy + ah);
ctx.line_to(cx, cy - ah);
}
ChevronDirection::Left => {
ctx.move_to(cx + ah, cy - hb);
ctx.line_to(cx + ah, cy + hb);
ctx.line_to(cx - ah, cy);
}
ChevronDirection::Right => {
ctx.move_to(cx - ah, cy - hb);
ctx.line_to(cx - ah, cy + hb);
ctx.line_to(cx + ah, cy);
}
}
ctx.close_path();
ctx.fill();
}
fn draw_glyph(
ctx: &mut dyn RenderContext,
rect: Rect,
view: &ChevronView,
color: &str,
style: &dyn super::style::ChevronStyle,
) {
let glyph = view.glyph_override.unwrap_or(match view.direction {
ChevronDirection::Up => "\u{25B2}", ChevronDirection::Down => "\u{25BC}", ChevronDirection::Left => "\u{25C0}", ChevronDirection::Right => "\u{25B6}", });
ctx.set_fill_color(color);
ctx.set_font(&format!("{}px sans-serif", style.glyph_size()));
ctx.set_text_align(TextAlign::Center);
ctx.set_text_baseline(TextBaseline::Middle);
ctx.fill_text(glyph, rect.center_x(), rect.center_y());
}
pub fn measure_chevron(settings: &ChevronSettings) -> (f64, f64) {
let s = settings.style.size();
(s, s)
}