termrs_core/widgets/
wrapper.rs1use std::{io::Error, marker::PhantomData};
2
3use crate::{
4 input::{Event, EventStatus},
5 render::{Margin, Position, RenderContext, Size},
6 widget::{EventContext, LayoutInfo, RenderInfo, Widget},
7};
8
9pub struct Wrapper<Message, Content, L, R>
11where
12 Content: Widget<Message, LayoutInfo = L, RenderInfo = R>,
13 L: LayoutInfo,
14 R: RenderInfo,
15{
16 content: Content,
17 phantom_message: PhantomData<Message>,
18
19 padding: Margin,
20}
21
22pub struct WrapperLayout<L: LayoutInfo> {
23 padding: Margin,
24 child_layout: L,
25}
26
27impl<L: LayoutInfo> LayoutInfo for WrapperLayout<L> {
28 fn bounds(&self) -> Size {
29 self.child_layout.bounds().add_margin(&self.padding)
30 }
31}
32
33impl<Message, Content, L, R> Wrapper<Message, Content, L, R>
34where
35 Content: Widget<Message, LayoutInfo = L, RenderInfo = R>,
36 L: LayoutInfo,
37 R: RenderInfo,
38{
39 pub fn new(content: Content) -> Self {
40 Self {
41 content,
42 phantom_message: PhantomData,
43 padding: Margin::default(),
44 }
45 }
46
47 pub fn with_padding(mut self, padding: Margin) -> Self {
48 self.padding = padding;
49 self
50 }
51}
52
53impl<Message, Content, L, R> Widget<Message> for Wrapper<Message, Content, L, R>
54where
55 Content: Widget<Message, LayoutInfo = L, RenderInfo = R>,
56 L: LayoutInfo,
57 R: RenderInfo,
58{
59 type LayoutInfo = WrapperLayout<L>;
60 type RenderInfo = R;
61
62 fn render(
63 &self,
64 position: Position,
65 layout: &Self::LayoutInfo,
66 context: &mut dyn RenderContext,
67 ) -> std::io::Result<Self::RenderInfo> {
68 let position = position.offset_u16(self.padding.left(), self.padding.top());
69
70 if let Some(position) = position {
71 self.content.render(position, &layout.child_layout, context)
72 } else {
73 Err(Error::other("Invalid position"))
74 }
75 }
76
77 fn layout(&self, available_size: Size) -> Self::LayoutInfo {
78 let available_size = available_size.sub_margin(&self.padding);
79
80 let child_layout = self.content.layout(available_size);
81
82 WrapperLayout {
83 child_layout,
84 padding: self.padding.clone(),
85 }
86 }
87
88 fn on_event(
89 &mut self,
90 event: &Event,
91 render_info: &Self::RenderInfo,
92 event_context: &mut dyn EventContext<Message>,
93 ) -> EventStatus {
94 self.content.on_event(event, render_info, event_context)
98 }
99}