Skip to main content

repose_core/
view.rs

1use crate::{Brush, Color, Modifier, Rect, Transform};
2use std::{rc::Rc, sync::Arc};
3
4pub type ViewId = u64;
5
6pub type ImageHandle = u64;
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub enum ImageFit {
9    Contain,
10    Cover,
11    FitWidth,
12    FitHeight,
13}
14
15pub type Callback = Rc<dyn Fn()>;
16pub type ScrollCallback = Rc<dyn Fn(crate::Vec2) -> crate::Vec2>;
17
18#[derive(Clone)]
19pub struct OverlayEntry {
20    pub id: u64,
21    pub view: Box<View>,
22}
23
24#[derive(Clone)]
25pub enum ViewKind {
26    Surface,
27    Box,
28    Row,
29    Column,
30    Stack,
31    OverlayHost,
32    ScrollV {
33        on_scroll: Option<ScrollCallback>,
34        set_viewport_height: Option<Rc<dyn Fn(f32)>>,
35        set_content_height: Option<Rc<dyn Fn(f32)>>,
36        get_scroll_offset: Option<Rc<dyn Fn() -> f32>>,
37        set_scroll_offset: Option<Rc<dyn Fn(f32)>>,
38    },
39    ScrollXY {
40        on_scroll: Option<ScrollCallback>,
41        set_viewport_width: Option<Rc<dyn Fn(f32)>>,
42        set_viewport_height: Option<Rc<dyn Fn(f32)>>,
43        set_content_width: Option<Rc<dyn Fn(f32)>>,
44        set_content_height: Option<Rc<dyn Fn(f32)>>,
45        get_scroll_offset_xy: Option<Rc<dyn Fn() -> (f32, f32)>>,
46        set_scroll_offset_xy: Option<Rc<dyn Fn(f32, f32)>>,
47    },
48    Text {
49        text: String,
50        color: Color,
51        font_size: f32,
52        soft_wrap: bool,
53        max_lines: Option<usize>,
54        overflow: TextOverflow,
55    },
56    Button {
57        on_click: Option<Callback>,
58    },
59    TextField {
60        state_key: ViewId,
61        hint: String,
62        multiline: bool,
63        on_change: Option<Rc<dyn Fn(String)>>,
64        on_submit: Option<Rc<dyn Fn(String)>>,
65    },
66    Checkbox {
67        checked: bool,
68        on_change: Option<Rc<dyn Fn(bool)>>,
69    },
70    RadioButton {
71        selected: bool,
72        on_select: Option<Callback>,
73    },
74    Switch {
75        checked: bool,
76        on_change: Option<Rc<dyn Fn(bool)>>,
77    },
78    Slider {
79        value: f32,
80        min: f32,
81        max: f32,
82        step: Option<f32>,
83        on_change: Option<CallbackF32>,
84    },
85    RangeSlider {
86        start: f32,
87        end: f32,
88        min: f32,
89        max: f32,
90        step: Option<f32>,
91        on_change: Option<CallbackRange>,
92    },
93    ProgressBar {
94        value: f32,
95        min: f32,
96        max: f32,
97        circular: bool,
98    },
99    Image {
100        handle: ImageHandle,
101        tint: Color, // multiplicative (WHITE = no tint)
102        fit: ImageFit,
103    },
104    Ellipse {
105        rect: Rect,
106        color: Color,
107    },
108    EllipseBorder {
109        rect: Rect,
110        color: Color,
111        width: f32, // screen-space width (px)
112    },
113}
114
115impl std::fmt::Debug for ViewKind {
116    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117        match self {
118            Self::Surface => f.write_str("Surface"),
119            Self::Box => f.write_str("Box"),
120            Self::Row => f.write_str("Row"),
121            Self::Column => f.write_str("Column"),
122            Self::Stack => f.write_str("Stack"),
123            Self::OverlayHost => f.write_str("OverlayHost"),
124            Self::ScrollV { .. } => f.write_str("ScrollV"),
125            Self::ScrollXY { .. } => f.write_str("ScrollXY"),
126            Self::Button { .. } => f.write_str("Button"),
127            Self::Image { .. } => f.write_str("Image"),
128            Self::Ellipse { .. } => f.write_str("Ellipse"),
129            Self::EllipseBorder { .. } => f.write_str("EllipseBorder"),
130            Self::Text { text, .. } => write!(f, "Text({:?})", text),
131            Self::TextField { hint, .. } => write!(f, "TextField({:?})", hint),
132            Self::Checkbox { checked, .. } => write!(f, "Checkbox({})", checked),
133            Self::RadioButton { selected, .. } => write!(f, "Radio({})", selected),
134            Self::Switch { checked, .. } => write!(f, "Switch({})", checked),
135            Self::Slider { value, .. } => write!(f, "Slider({})", value),
136            Self::RangeSlider { start, end, .. } => write!(f, "Range({}..{})", start, end),
137            Self::ProgressBar { value, .. } => write!(f, "Progress({})", value),
138        }
139    }
140}
141
142#[derive(Clone, Debug)]
143pub struct View {
144    pub id: ViewId,
145    pub kind: ViewKind,
146    pub modifier: Modifier,
147    pub children: Vec<View>,
148    pub semantics: Option<crate::semantics::Semantics>,
149}
150
151impl View {
152    pub fn new(id: ViewId, kind: ViewKind) -> Self {
153        View {
154            id,
155            kind,
156            modifier: Modifier::default(),
157            children: vec![],
158            semantics: None,
159        }
160    }
161    pub fn modifier(mut self, m: Modifier) -> Self {
162        self.modifier = m;
163        self
164    }
165    pub fn with_children(mut self, kids: Vec<View>) -> Self {
166        self.children = kids;
167        self
168    }
169    pub fn semantics(mut self, s: crate::semantics::Semantics) -> Self {
170        self.semantics = Some(s);
171        self
172    }
173}
174
175/// Renderable scene
176#[derive(Clone, Debug, Default)]
177pub struct Scene {
178    pub clear_color: Color,
179    pub nodes: Vec<SceneNode>,
180}
181
182#[derive(Clone, Debug)]
183pub enum SceneNode {
184    Rect {
185        rect: Rect,
186        brush: Brush,
187        radius: f32,
188    },
189    Border {
190        rect: Rect,
191        color: Color,
192        width: f32,
193        radius: f32,
194    },
195    Text {
196        rect: Rect,
197        text: Arc<str>,
198        color: Color,
199        size: f32,
200    },
201    Ellipse {
202        rect: Rect,
203        brush: Brush,
204    },
205    EllipseBorder {
206        rect: Rect,
207        color: Color,
208        width: f32, // screen-space width (px)
209    },
210    PushClip {
211        rect: Rect,
212        radius: f32,
213    },
214    PopClip,
215    PushTransform {
216        transform: Transform,
217    },
218    PopTransform,
219    Image {
220        rect: Rect,
221        handle: ImageHandle,
222        tint: Color,
223        fit: ImageFit,
224    },
225}
226
227pub type CallbackF32 = Rc<dyn Fn(f32)>;
228pub type CallbackRange = Rc<dyn Fn(f32, f32)>;
229
230#[derive(Clone, Copy, Debug, PartialEq, Eq)]
231pub enum TextOverflow {
232    Visible,
233    Clip,
234    Ellipsis,
235}