omp_tui/components/
icon.rs1use omp_core::Str;
2
3use crate::{
4 component::{Component, PaintCtx, Slot, next_slot},
5 frame::Rect,
6 props::{Prop, PropValue, Props},
7 rich::cell_width,
8};
9
10pub struct Icon {
12 props: Props,
13 slot: Slot,
14 name: Str,
15}
16
17impl Icon {
18 pub fn new() -> Self {
20 Self { props: Props::new(), slot: next_slot(), name: Str::default() }
21 }
22
23 pub fn named(name: impl Into<Str>) -> Self {
25 Self { name: name.into(), ..Self::new() }
26 }
27
28 pub fn with(mut self, prop: Prop, value: impl Into<PropValue>) -> Self {
30 self.props.set(prop, value);
31 self
32 }
33
34 pub fn with_str(self, prop: Prop, value: &str) -> Self {
36 self.with(prop, value)
37 }
38
39 fn glyph<'a>(&'a self, ctx: &'a crate::UiContext) -> &'a str {
40 ctx.charset.icon_named(&self.name).unwrap_or(&self.name)
41 }
42}
43
44impl Default for Icon {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl Component for Icon {
51 fn props(&self) -> &Props {
52 &self.props
53 }
54
55 fn props_mut(&mut self) -> &mut Props {
56 &mut self.props
57 }
58
59 fn slot(&self) -> Slot {
60 self.slot
61 }
62
63 fn measure(&mut self, ctx: &crate::UiContext) -> (u16, u16) {
64 let width = cell_width(self.glyph(ctx));
65 (width, width)
66 }
67
68 fn height(&mut self, _ctx: &crate::UiContext, _width: u16) -> u16 {
69 1
70 }
71
72 fn paint(&mut self, pc: &mut PaintCtx<'_>, rect: Rect) {
73 if rect.y >= pc.clip || rect.width == 0 || rect.height == 0 {
74 return;
75 }
76 let glyph = self.glyph(pc.ctx);
77 let style = self.props.style(&pc.ctx.theme);
78 let room = rect.width;
79 if cell_width(glyph) <= room {
80 pc.frame.put(rect.x, rect.y, glyph, style);
81 }
82 }
83}