1use prism::drawable::{Component, Drawable, SizedTree, RequestTree, Rect, DynClone, clone_trait_object};
2use prism::{Context, IS_MOBILE};
3use prism::event::{OnEvent, Event, TickEvent};
4use prism::layout::{Area, Column, Offset, Padding, Size, Row};
5use prism::display::Opt;
6use prism::canvas::{Area as CanvasArea, Item as CanvasItem};
7
8use crate::interface::navigation::Pages;
9use crate::navigation::NavigationEvent;
10
11#[derive(Component, Clone, Debug)]
12pub enum Interface {
13 Mobile {
14 layout: Column,
15 body: Box<dyn Body>,
16 keyboard: Opt<Box<dyn Drawable>>,
17 navigator: Option<Opt<Box<dyn Navigator>>>,
18 },
19
20 Desktop {
21 layout: Row,
22 navigator: Option<Opt<Box<dyn Navigator>>>,
23 body: Box<dyn Body>
24 },
25
26 Web {
27 layout: Column,
28 navigator: Option<Opt<Box<dyn Navigator>>>,
29 body: Box<dyn Body>
30 }
31}
32
33
34impl OnEvent for Interface {
35 fn on_event(&mut self, _ctx: &mut Context, _sized: &SizedTree, mut event: Box<dyn Event>) -> Vec<Box<dyn Event>> {
36 if event.downcast_mut::<NavigationEvent>().is_some() && let Interface::Mobile{keyboard, ..} = self {
37 keyboard.display(false);
38 }
39
40 if let Some(NavigationEvent::Push(_, v)) = event.downcast_mut::<NavigationEvent>() {*v = if let Interface::Desktop{navigator,..} = self && navigator.is_some() {vec![0]} else {vec![]};}
41
42 if let Interface::Mobile{keyboard, ..} = self
43 && let Some(ShowKeyboard(b)) = event.downcast_ref::<ShowKeyboard>() {
44 keyboard.display(*b);
45 }
46
47 if IS_MOBILE && event.downcast_ref::<TickEvent>().is_some() {
48 let is_root = self.pages().is_root();
49 if let Some(s) = self.navigator().as_mut() { s.display(is_root) }
50 }
51
52 vec![event]
53 }
54}
55
56impl Interface {
57 pub fn desktop(navigator: Option<Box<dyn Navigator>>, body: impl Body + 'static) -> Self {
58 Interface::Desktop {
59 layout: Row::start(0.0),
60 navigator: navigator.map(|n| Opt::new(n, true)),
61 body: Box::new(body)
62 }
63 }
64
65 pub fn mobile(navigator: Option<Box<dyn Navigator>>, body: impl Body + 'static, keyboard: impl Drawable + 'static) -> Self {
66 Interface::Mobile {
67 layout: Column::new(0.0, Offset::Center, Size::Fit, Padding::default(), None),
68 body: Box::new(body),
69 keyboard: Opt::new(Box::new(keyboard), false),
70 navigator: navigator.map(|n| Opt::new(n, true)),
71 }
72 }
73
74 pub fn web(navigator: Option<Box<dyn Navigator>>, body: impl Body + 'static) -> Self {
75 let layout = Column::new(0.0, Offset::Start, Size::Fill, Padding::default(), None);
76 Interface::Web {
77 layout,
78 navigator: navigator.map(|n| Opt::new(n, true)),
79 body: Box::new(body),
80 }
81 }
82
83 pub fn pages(&mut self) -> &mut Pages {
84 match self {
85 Interface::Desktop {body, ..} => body.pages(),
86 Interface::Mobile {body, ..} => body.pages(),
87 Interface::Web {body, ..} => body.pages(),
88 }
89 }
90
91 pub fn navigator(&mut self) -> &mut Option<Opt<Box<dyn Navigator>>> {
92 match self {
93 Interface::Desktop {navigator, ..} => navigator,
94 Interface::Mobile {navigator, ..} => navigator,
95 Interface::Web {navigator, ..} => navigator,
96 }
97 }
98}
99
100#[derive(Debug, Clone)]
102pub struct ShowKeyboard(pub bool);
103
104impl Event for ShowKeyboard {
105 fn pass(self: Box<Self>, _ctx: &mut Context, children: &[Area]) -> Vec<Option<Box<dyn Event>>> {
106 children.iter().map(|_| Some(self.clone() as Box<dyn Event>)).collect()
107 }
108}
109
110pub trait Body: Drawable + DynClone + std::fmt::Debug + 'static {
111 fn pages(&mut self) -> &mut Pages;
112}
113
114clone_trait_object!(Body);
115
116pub trait Navigator: Drawable + DynClone + std::fmt::Debug + 'static {}
117
118clone_trait_object!(Navigator);
119
120impl Drawable for Box<dyn Navigator> {
121 fn request_size(&self) -> RequestTree {Drawable::request_size(&**self)}
122 fn build(&self, size: (f32, f32), request: RequestTree) -> SizedTree {
123 Drawable::build(&**self, size, request)
124 }
125 fn draw(&self, sized: &SizedTree, offset: (f32, f32), bound: Rect) -> Vec<(CanvasArea, CanvasItem)> {
126 Drawable::draw(&**self, sized, offset, bound)
127 }
128
129 fn name(&self) -> String {Drawable::name(&**self)}
130
131 fn event(&mut self, ctx: &mut Context, sized: &SizedTree, event: Box<dyn Event>) {
132 Drawable::event(&mut **self, ctx, sized, event)
133 }
134}
135
136