use std::sync::Arc;
use gpui::{Hsla, IntoElement, Point, svg};
use strum::{EnumIter, EnumString, IntoStaticStr};
use crate::prelude::*;
const ICON_DECORATION_SIZE: Pixels = px(11.);
#[derive(Debug, PartialEq, Eq, Copy, Clone, EnumIter, EnumString, IntoStaticStr)]
#[strum(serialize_all = "snake_case")]
pub enum KnockoutIconName {
XFg,
XBg,
DotFg,
DotBg,
TriangleFg,
TriangleBg,
}
impl KnockoutIconName {
pub fn path(&self) -> Arc<str> {
let file_stem: &'static str = self.into();
format!("icons/knockouts/{file_stem}.svg").into()
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone, EnumIter, EnumString)]
pub enum IconDecorationKind {
X,
Dot,
Triangle,
}
impl IconDecorationKind {
fn fg(&self) -> KnockoutIconName {
match self {
Self::X => KnockoutIconName::XFg,
Self::Dot => KnockoutIconName::DotFg,
Self::Triangle => KnockoutIconName::TriangleFg,
}
}
fn bg(&self) -> KnockoutIconName {
match self {
Self::X => KnockoutIconName::XBg,
Self::Dot => KnockoutIconName::DotBg,
Self::Triangle => KnockoutIconName::TriangleBg,
}
}
}
#[derive(IntoElement)]
pub struct IconDecoration {
kind: IconDecorationKind,
color: Hsla,
knockout_color: Hsla,
knockout_hover_color: Hsla,
size: Pixels,
position: Point<Pixels>,
group_name: Option<SharedString>,
}
impl IconDecoration {
pub fn new(kind: IconDecorationKind, knockout_color: Hsla, cx: &App) -> Self {
let color = cx.theme().colors().icon;
let position = Point::default();
Self {
kind,
color,
knockout_color,
knockout_hover_color: knockout_color,
size: ICON_DECORATION_SIZE,
position,
group_name: None,
}
}
pub fn kind(mut self, kind: IconDecorationKind) -> Self {
self.kind = kind;
self
}
pub fn color(mut self, color: Hsla) -> Self {
self.color = color;
self
}
pub fn knockout_color(mut self, color: Hsla) -> Self {
self.knockout_color = color;
self
}
pub fn knockout_hover_color(mut self, color: Hsla) -> Self {
self.knockout_hover_color = color;
self
}
pub fn position(mut self, position: Point<Pixels>) -> Self {
self.position = position;
self
}
pub fn size(mut self, size: Pixels) -> Self {
self.size = size;
self
}
pub fn group_name(mut self, name: Option<SharedString>) -> Self {
self.group_name = name;
self
}
}
impl RenderOnce for IconDecoration {
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let size = self.size;
let foreground = svg()
.absolute()
.bottom_0()
.right_0()
.size(size)
.path(self.kind.fg().path())
.text_color(self.color);
let background = svg()
.absolute()
.bottom_0()
.right_0()
.size(size)
.path(self.kind.bg().path())
.text_color(self.knockout_color)
.map(|this| match self.group_name {
Some(group_name) => this.group_hover(group_name, |style| {
style.text_color(self.knockout_hover_color)
}),
None => this.hover(|style| style.text_color(self.knockout_hover_color)),
});
div()
.size(size)
.flex_none()
.absolute()
.bottom(self.position.y)
.right(self.position.x)
.child(background)
.child(foreground)
}
}