use omp_core::Str;
use crate::{
component::{Component, PaintCtx, Slot, next_slot},
frame::Rect,
props::{Prop, PropValue, Props},
rich::cell_width,
};
pub struct Icon {
props: Props,
slot: Slot,
name: Str,
}
impl Icon {
pub fn new() -> Self {
Self { props: Props::new(), slot: next_slot(), name: Str::default() }
}
pub fn named(name: impl Into<Str>) -> Self {
Self { name: name.into(), ..Self::new() }
}
pub fn with(mut self, prop: Prop, value: impl Into<PropValue>) -> Self {
self.props.set(prop, value);
self
}
pub fn with_str(self, prop: Prop, value: &str) -> Self {
self.with(prop, value)
}
fn glyph<'a>(&'a self, ctx: &'a crate::UiContext) -> &'a str {
ctx.charset.icon_named(&self.name).unwrap_or(&self.name)
}
}
impl Default for Icon {
fn default() -> Self {
Self::new()
}
}
impl Component for Icon {
fn props(&self) -> &Props {
&self.props
}
fn props_mut(&mut self) -> &mut Props {
&mut self.props
}
fn slot(&self) -> Slot {
self.slot
}
fn measure(&mut self, ctx: &crate::UiContext) -> (u16, u16) {
let width = cell_width(self.glyph(ctx));
(width, width)
}
fn height(&mut self, _ctx: &crate::UiContext, _width: u16) -> u16 {
1
}
fn paint(&mut self, pc: &mut PaintCtx<'_>, rect: Rect) {
if rect.y >= pc.clip || rect.width == 0 || rect.height == 0 {
return;
}
let glyph = self.glyph(pc.ctx);
let style = self.props.style(&pc.ctx.theme);
let room = rect.width;
if cell_width(glyph) <= room {
pc.frame.put(rect.x, rect.y, glyph, style);
}
}
}