Skip to main content

omp_tui/components/
icon.rs

1use 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
10/// A theme-resolved glyph backing the `<icon>` markup tag.
11pub struct Icon {
12	props: Props,
13	slot:  Slot,
14	name:  Str,
15}
16
17impl Icon {
18	/// Creates an icon with no assigned name.
19	pub fn new() -> Self {
20		Self { props: Props::new(), slot: next_slot(), name: Str::default() }
21	}
22
23	/// Creates an icon with the requested theme glyph name.
24	pub fn named(name: impl Into<Str>) -> Self {
25		Self { name: name.into(), ..Self::new() }
26	}
27
28	/// Sets one icon property.
29	pub fn with(mut self, prop: Prop, value: impl Into<PropValue>) -> Self {
30		self.props.set(prop, value);
31		self
32	}
33
34	/// Sets one icon property from a string.
35	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}