termint/widgets/
widget.rs1use std::{
2 any::{Any, TypeId},
3 fmt,
4};
5
6use crate::{
7 buffer::Buffer,
8 geometry::{Rect, Vec2},
9 widgets::cache::Cache,
10};
11
12pub trait Widget: Any {
23 fn render(&self, buffer: &mut Buffer, rect: Rect, cache: &mut Cache);
26
27 fn height(&self, size: &Vec2) -> usize;
30
31 fn width(&self, size: &Vec2) -> usize;
34
35 fn children(&self) -> Vec<&Element> {
37 vec![]
38 }
39}
40
41impl dyn Widget {
42 pub fn as_any(&self) -> &dyn Any {
43 self
44 }
45
46 pub fn as_any_mut(&mut self) -> &mut dyn Any {
47 self
48 }
49}
50
51impl fmt::Debug for dyn Widget {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "Converted widget")
54 }
55}
56
57#[derive(Debug)]
64pub struct Element {
65 pub type_id: TypeId,
66 pub widget: Box<dyn Widget>,
67}
68
69impl Element {
70 pub fn new<W>(widget: W) -> Self
81 where
82 W: Widget + 'static,
83 {
84 Self {
85 type_id: TypeId::of::<W>(),
86 widget: Box::new(widget),
87 }
88 }
89
90 pub fn map<W: Widget + 'static, F: FnOnce(W) -> W>(self, f: F) -> Self {
91 let Element { type_id: _, widget } = self;
92 let boxed_any: Box<dyn Any> = widget;
93
94 match boxed_any.downcast::<W>() {
95 Ok(bx) => {
96 let new = f(*bx);
97 Self {
98 type_id: TypeId::of::<W>(),
99 widget: Box::new(new),
100 }
101 }
102 Err(orig) => {
103 let widget: Box<dyn Widget> = *orig
104 .downcast::<Box<dyn Widget>>()
105 .expect("Original type must be Box<dyn Widget>");
106 let type_id = widget.as_ref().type_id();
107
108 Self { type_id, widget }
109 }
110 }
111 }
112
113 pub fn downcast_ref<W: Widget>(&self) -> Option<&W> {
116 self.widget.as_ref().as_any().downcast_ref::<W>()
117 }
118
119 pub fn downcast_mut<W: Widget>(&mut self) -> Option<&mut W> {
122 self.widget.as_mut().as_any_mut().downcast_mut::<W>()
123 }
124}
125
126impl Widget for Element {
127 fn render(&self, buffer: &mut Buffer, rect: Rect, cache: &mut Cache) {
128 self.widget.render(buffer, rect, cache)
129 }
130
131 fn height(&self, size: &Vec2) -> usize {
132 self.widget.height(size)
133 }
134
135 fn width(&self, size: &Vec2) -> usize {
136 self.widget.width(size)
137 }
138
139 fn children(&self) -> Vec<&Element> {
140 self.widget.children()
141 }
142}