1mod program;
3
4pub use program::Program;
5
6use crate::core::event;
7use crate::core::layout::{self, Layout};
8use crate::core::mouse;
9use crate::core::renderer;
10use crate::core::widget::tree::{self, Tree};
11use crate::core::widget::{self, Widget};
12use crate::core::{Event, Length, Rectangle, Shell, Size};
13use crate::renderer::wgpu::primitive;
14
15use std::marker::PhantomData;
16
17pub use crate::Action;
18pub use crate::graphics::Viewport;
19pub use primitive::{Pipeline, Primitive, Storage};
20
21pub struct Shader<Message, P: Program<Message>> {
26 width: Length,
27 height: Length,
28 program: P,
29 _message: PhantomData<Message>,
30}
31
32impl<Message, P: Program<Message>> Shader<Message, P> {
33 pub fn new(program: P) -> Self {
35 Self {
36 width: Length::Fixed(100.0),
37 height: Length::Fixed(100.0),
38 program,
39 _message: PhantomData,
40 }
41 }
42
43 pub fn width(mut self, width: impl Into<Length>) -> Self {
45 self.width = width.into();
46 self
47 }
48
49 pub fn height(mut self, height: impl Into<Length>) -> Self {
51 self.height = height.into();
52 self
53 }
54}
55
56impl<Message, P> widget::Meta for Shader<Message, P> where P: Program<Message> {}
57
58impl<P, Message, Theme, Renderer> Widget<Message, Theme, Renderer> for Shader<Message, P>
59where
60 P: Program<Message>,
61 Renderer: primitive::Renderer,
62{
63 fn tag(&self) -> tree::Tag {
64 struct Tag<T>(T);
65 tree::Tag::of::<Tag<P::State>>()
66 }
67
68 fn state(&self) -> tree::State {
69 tree::State::new(P::State::default())
70 }
71
72 fn size(&self) -> Size<Length> {
73 Size {
74 width: self.width,
75 height: self.height,
76 }
77 }
78
79 fn layout(&mut self, tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits) {
80 tree.size = layout::atomic(limits, self.width, self.height);
81 }
82
83 fn update(
84 &mut self,
85 tree: &mut Tree,
86 event: &Event,
87 layout: Layout,
88 cursor: mouse::Cursor,
89 _renderer: &Renderer,
90 shell: &mut Shell<'_, Message>,
91 _viewport: &Rectangle,
92 ) {
93 let bounds = layout.bounds();
94
95 let state = tree.state.downcast_mut::<P::State>();
96
97 if let Some(action) = self.program.update(state, event, bounds, cursor) {
98 let (message, redraw_request, event_status) = action.into_inner();
99
100 shell.request_redraw_at(redraw_request);
101
102 if let Some(message) = message {
103 shell.publish(message);
104 }
105
106 if event_status == event::Status::Captured {
107 shell.capture_event();
108 }
109 }
110 }
111
112 fn mouse_interaction(
113 &self,
114 tree: &Tree,
115 layout: Layout,
116 cursor: mouse::Cursor,
117 _viewport: &Rectangle,
118 _renderer: &Renderer,
119 ) -> mouse::Interaction {
120 let bounds = layout.bounds();
121 let state = tree.state.downcast_ref::<P::State>();
122
123 self.program.mouse_interaction(state, bounds, cursor)
124 }
125
126 fn draw(
127 &self,
128 tree: &widget::Tree,
129 renderer: &mut Renderer,
130 _theme: &Theme,
131 _style: &renderer::Style,
132 layout: Layout,
133 cursor_position: mouse::Cursor,
134 _viewport: &Rectangle,
135 ) {
136 let bounds = layout.bounds();
137 let state = tree.state.downcast_ref::<P::State>();
138
139 renderer.draw_primitive(bounds, self.program.draw(state, cursor_position, bounds));
140 }
141}
142
143impl<Message, T> Program<Message> for &T
144where
145 T: Program<Message>,
146{
147 type State = T::State;
148 type Primitive = T::Primitive;
149
150 fn update(
151 &self,
152 state: &mut Self::State,
153 event: &Event,
154 bounds: Rectangle,
155 cursor: mouse::Cursor,
156 ) -> Option<Action<Message>> {
157 T::update(self, state, event, bounds, cursor)
158 }
159
160 fn draw(
161 &self,
162 state: &Self::State,
163 cursor: mouse::Cursor,
164 bounds: Rectangle,
165 ) -> Self::Primitive {
166 T::draw(self, state, cursor, bounds)
167 }
168
169 fn mouse_interaction(
170 &self,
171 state: &Self::State,
172 bounds: Rectangle,
173 cursor: mouse::Cursor,
174 ) -> mouse::Interaction {
175 T::mouse_interaction(self, state, bounds, cursor)
176 }
177}