1#![allow(unused_must_use)]
5
6use everything_plugin::ui::winio::prelude::*;
7
8use crate::{App, HANDLER};
9
10#[allow(dead_code)]
11pub fn main() {
12 winio::ui::App::new("rs.compio.winio.widgets")
18 .unwrap()
19 .run::<MainModel>(())
20 .unwrap();
21}
22
23pub struct MainModel {
24 window: Child<View>,
25 ulabel: Child<Label>,
26 plabel: Child<Label>,
27 uentry: Child<Edit>,
28 pentry: Child<Edit>,
29 pcheck: Child<CheckBox>,
30 canvas: Child<Canvas>,
31 combo: Child<ComboBox>,
32 list: Child<ObservableVec<String>>,
33 index: Option<usize>,
34 radio_group: Child<RadioButtonGroup>,
35 rindex: usize,
36 push_button: Child<Button>,
37 pop_button: Child<Button>,
38 show_button: Child<Button>,
39 progress: Child<Progress>,
40 mltext: Child<TextBox>,
41}
42
43#[derive(Debug)]
44pub enum MainMessage {
45 Noop,
46 List(ObservableVecEvent<String>),
47 Select,
48 Push,
49 Pop,
50 Show,
51 RSelect(usize),
52 PasswordCheck,
53 OptionsPage(OptionsPageMessage<App>),
54}
55
56impl From<OptionsPageMessage<App>> for MainMessage {
57 fn from(value: OptionsPageMessage<App>) -> Self {
58 Self::OptionsPage(value)
59 }
60}
61
62impl Component for MainModel {
63 type Event = ();
64 type Init<'a> = OptionsPageInit<'a, App>;
65 type Message = MainMessage;
66 type Error = Error;
67
68 async fn init(
69 mut init: Self::Init<'_>,
70 sender: &ComponentSender<Self>,
71 ) -> Result<Self, Self::Error> {
72 let mut window = init.window(sender).await?;
74 window.set_size(Size::new(800.0, 600.0));
76
77 let canvas = Child::<Canvas>::init(&window).await?;
78 let mut ulabel = Child::<Label>::init(&window).await?;
79 ulabel.set_text("Username:");
80 ulabel.set_halign(HAlign::Right);
81 let mut plabel = Child::<Label>::init(&window).await?;
82 plabel.set_text("Password:");
83 plabel.set_halign(HAlign::Right);
84 let mut uentry = Child::<Edit>::init(&window).await?;
85 uentry.set_text("AAA");
86 let mut pentry = Child::<Edit>::init(&window).await?;
87 pentry.set_text("123456");
88 pentry.set_password(true);
89 let mut pcheck = Child::<CheckBox>::init(&window).await?;
90 pcheck.set_text("Show");
91 pcheck.set_checked(false);
92 let combo = Child::<ComboBox>::init(&window).await?;
93 let mut list = Child::<ObservableVec<String>>::init(Vec::new())
94 .await
95 .unwrap();
96 list.push("烫烫烫".to_string());
98 list.push("昍昍昍".to_string());
99 list.push("フフフフフフ".to_string());
100 list.push("쳌쳌쳌".to_string());
101 let mut r1 = Child::<RadioButton>::init(&window).await?;
102 r1.set_text("屯屯屯");
103 r1.set_checked(true);
104 let mut r2 = Child::<RadioButton>::init(&window).await?;
105 r2.set_text("锟斤拷");
106 let mut r3 = Child::<RadioButton>::init(&window).await?;
107 r3.set_text("╠╠╠");
108 let radio_group = Child::<RadioButtonGroup>::init(vec![r1, r2, r3]).await?;
110
111 let mut push_button = Child::<Button>::init(&window).await?;
112 push_button.set_text("Push");
113 let mut pop_button = Child::<Button>::init(&window).await?;
114 pop_button.set_text("Pop");
115 let mut show_button = Child::<Button>::init(&window).await?;
116 show_button.set_text("Show");
117 let mut progress = Child::<Progress>::init(&window).await?;
118 progress.set_indeterminate(true);
119 let mut mltext = Child::<TextBox>::init(&window).await?;
120 HANDLER.with_app(|a| mltext.set_text(&a.config().s));
121
122 window.show();
123
124 Ok(Self {
125 window,
126 ulabel,
127 plabel,
128 uentry,
129 pentry,
130 pcheck,
131 canvas,
132 combo,
133 list,
134 index: None,
135 radio_group,
136 rindex: 0,
137 push_button,
138 pop_button,
139 show_button,
140 progress,
141 mltext,
142 })
143 }
144
145 async fn start(&mut self, sender: &ComponentSender<Self>) -> ! {
146 start! {
147 sender, default: MainMessage::Noop,
148 self.pcheck => {
149 CheckBoxEvent::Click => MainMessage::PasswordCheck,
150 },
151 self.combo => {
152 ComboBoxEvent::Select => MainMessage::Select,
153 },
154 self.push_button => {
155 ButtonEvent::Click => MainMessage::Push,
156 },
157 self.pop_button => {
158 ButtonEvent::Click => MainMessage::Pop,
159 },
160 self.show_button => {
161 ButtonEvent::Click => MainMessage::Show,
162 },
163 self.list => {
164 e => MainMessage::List(e),
165 },
166 self.radio_group => {
167 RadioButtonGroupEvent::Click(i) => MainMessage::RSelect(i)
168 }
169 }
170 }
171
172 async fn update_children(&mut self) -> Result<bool, Self::Error> {
173 update_children!(self.window, self.canvas, self.radio_group)
174 }
175
176 async fn update(
177 &mut self,
178 message: Self::Message,
179 sender: &ComponentSender<Self>,
180 ) -> Result<bool, Self::Error> {
181 Ok(match message {
183 MainMessage::Noop => false,
184 MainMessage::PasswordCheck => {
185 self.pentry.set_password(!self.pcheck.is_checked()?);
186 true
187 }
188 MainMessage::List(e) => {
189 self.pop_button.set_enabled(!self.list.is_empty());
190 self.combo
191 .emit(ComboBoxMessage::from_observable_vec_event(e))
192 .await?
193 }
194 MainMessage::Select => {
195 self.index = self.combo.selection()?;
196 false
197 }
198 MainMessage::Push => {
199 self.list.push(self.radio_group[self.rindex].text()?);
200 false
201 }
202 MainMessage::Pop => {
203 self.list.pop();
204 false
205 }
206 MainMessage::RSelect(i) => {
207 self.rindex = i;
208 false
209 }
210 MainMessage::Show => {
211 MessageBox::new()
212 .title("Show selected item")
213 .message(
214 self.index
215 .and_then(|index| self.list.get(index))
216 .map(|s| s.as_str())
217 .unwrap_or("No selection."),
218 )
219 .buttons(MessageBoxButton::Ok)
220 .show(unsafe { BorrowedWindow::win32(self.window.as_container().as_win32()) })
222 .await;
223 false
224 }
225 MainMessage::OptionsPage(m) => {
226 tracing::debug!(?m, "Options page message");
227 match m {
228 OptionsPageMessage::Redraw => true,
229 OptionsPageMessage::Close => {
230 sender.output(());
231 false
232 }
233 OptionsPageMessage::Save(config, tx) => {
234 config.s = self.mltext.text()?;
235 tx.send(config).unwrap();
236 false
237 }
238 }
239 }
240 })
241 }
242
243 fn render(&mut self, _sender: &ComponentSender<Self>) -> Result<(), Self::Error> {
244 let csize = self.window.size()?;
245 {
246 let mut cred_panel = layout! {
247 Grid::from_str("auto,1*,auto", "1*,auto,auto,1*").unwrap(),
248 self.ulabel => { column: 0, row: 1, valign: VAlign::Center },
249 self.uentry => { column: 1, row: 1, margin: Margin::new_all_same(4.0) },
250 self.plabel => { column: 0, row: 2, valign: VAlign::Center },
251 self.pentry => { column: 1, row: 2, margin: Margin::new_all_same(4.0) },
252 self.pcheck => { column: 2, row: 2 },
253 };
254
255 let mut rgroup_panel = Grid::from_str("auto", "1*,auto,auto,auto,1*").unwrap();
256 for (i, rb) in self.radio_group.iter_mut().enumerate() {
257 rgroup_panel.push(rb).row(i + 1).finish();
258 }
259
260 let mut buttons_panel = layout! {
261 StackPanel::new(Orient::Vertical),
262 self.push_button => { margin: Margin::new_all_same(4.0) },
263 self.pop_button => { margin: Margin::new_all_same(4.0) },
264 self.show_button => { margin: Margin::new_all_same(4.0) },
265 };
266
267 let mut root_panel = layout! {
268 Grid::from_str("1*,1*,1*", "1*,auto,1*").unwrap(),
269 cred_panel => { column: 1, row: 0 },
270 rgroup_panel => { column: 2, row: 0, halign: HAlign::Center },
271 self.canvas => { column: 0, row: 1, row_span: 2 },
272 self.combo => { column: 1, row: 1, halign: HAlign::Center },
273 self.progress => { column: 2, row: 1 },
274 self.mltext => { column: 1, row: 2, margin: Margin::new_all_same(8.0) },
275 buttons_panel => { column: 2, row: 2 },
276 };
277
278 root_panel.set_size(csize);
279 }
280
281 let size = self.canvas.size()?;
282 let is_dark = ColorTheme::current()? == ColorTheme::Dark;
283 let back_color = if is_dark {
284 Color::new(255, 255, 255, 255)
285 } else {
286 Color::new(0, 0, 0, 255)
287 };
288 let brush = SolidColorBrush::new(back_color);
289 let pen = BrushPen::new(&brush, 1.0);
290 let mut ctx = self.canvas.context()?;
291 let cx = size.width / 2.0;
292 let cy = size.height / 2.0;
293 let r = cx.min(cy) - 2.0;
294 ctx.draw_pie(
295 &pen,
296 Rect::new(Point::new(cx - r, cy - r), Size::new(r * 2.0, r * 2.0)),
297 std::f64::consts::PI,
298 std::f64::consts::PI * 2.0,
299 );
300
301 let brush2 = LinearGradientBrush::new(
302 [
303 GradientStop::new(Color::new(0x87, 0xCE, 0xEB, 0xFF), 0.0),
304 GradientStop::new(back_color, 1.0),
305 ],
306 RelativePoint::zero(),
307 RelativePoint::new(0.0, 1.0),
308 );
309 let pen2 = BrushPen::new(&brush2, 1.0);
310 ctx.draw_round_rect(
311 &pen2,
312 Rect::new(
313 Point::new(cx - r - 1.0, cy - r - 1.0),
314 Size::new(r * 2.0 + 2.0, r * 1.618 + 2.0),
315 ),
316 Size::new(r / 10.0, r / 10.0),
317 );
318 let mut path = ctx.create_path_builder(Point::new(cx + r + 1.0 - r / 10.0, cy))?;
319 path.add_arc(
320 Point::new(cx, cy + r * 0.618 + 1.0),
321 Size::new(r + 1.0 - r / 10.0, r * 0.382 / 2.0),
322 0.0,
323 std::f64::consts::PI,
324 true,
325 );
326 path.add_line(Point::new(cx - r - 1.0 + r / 10.0, cy));
327 let path = path.build(false)?;
328 ctx.draw_path(&pen, &path);
329 let brush3 = RadialGradientBrush::new(
330 [
331 GradientStop::new(Color::new(0xF5, 0xF5, 0xF5, 0xFF), 0.0),
332 GradientStop::new(
333 Color::accent().unwrap_or(Color::new(0xFF, 0xC0, 0xCB, 0xFF)),
334 1.0,
335 ),
336 ],
337 RelativePoint::new(0.5, 0.5),
338 RelativePoint::new(0.2, 0.5),
339 RelativeSize::new(0.5, 0.5),
340 );
341 let font = DrawingFontBuilder::new()
342 .family("Arial")
343 .size(r / 5.0)
344 .halign(HAlign::Center)
345 .valign(VAlign::Bottom)
346 .build();
347 ctx.draw_str(&brush3, font, Point::new(cx, cy), "Hello world!");
348 Ok(())
349 }
350}