everything_plugin/ui/
winio.rs1use futures_channel::mpsc;
7use futures_util::StreamExt;
8use tracing::debug;
9use windows_sys::Win32::{Foundation::HWND, UI::WindowsAndMessaging::WS_OVERLAPPEDWINDOW};
10
11use crate::ui::{OptionsPageInternalMessage, OptionsPageLoadArgs, PageHandle};
12
13pub use winio;
14
15pub mod prelude {
16 pub use super::{super::OptionsPageMessage, OptionsPageInit};
17 pub use crate::PluginApp;
18 pub use winio::{Error, elm::*, handle::*, layout::*, primitive::*, ui::*, widgets::*};
21}
22use prelude::*;
23
24pub trait OptionsPageComponent<'a>:
25 Component<
26 Init<'a> = OptionsPageInit<'a, Self::App>,
27 Message: From<OptionsPageMessage<Self::App>>,
28 > + 'static
29{
30 type App: PluginApp;
31}
32
33impl<'a, T, A: PluginApp> OptionsPageComponent<'a> for T
34where
35 T: Component<Init<'a> = OptionsPageInit<'a, A>, Message: From<OptionsPageMessage<A>>> + 'static,
36{
37 type App = A;
38}
39
40pub fn spawn<'a, T: OptionsPageComponent<'a>>(args: OptionsPageLoadArgs) -> PageHandle<T::App> {
41 let parent: usize = args.parent as usize;
43
44 let (tx, rx) = mpsc::unbounded();
45 let thread_handle = std::thread::spawn(move || {
46 let parent: HWND = parent as HWND;
47 run::<T>(OptionsPageInit {
48 parent: unsafe { BorrowedContainer::win32(parent) },
49 rx: Some(rx),
50 })
51 .ok();
52 });
54 PageHandle { thread_handle, tx }
55}
56
57pub fn run<'a, T: OptionsPageComponent<'a>>(
58 init: OptionsPageInit<'a, T::App>,
59) -> Result<T::Event, T::Error> {
60 App::new("").unwrap().run::<T>(init)
63}
64
65pub struct OptionsPageInit<'a, A: PluginApp> {
66 parent: BorrowedContainer<'a>,
68
69 rx: Option<mpsc::UnboundedReceiver<OptionsPageInternalMessage<A>>>,
73}
74
75impl<'a, A: PluginApp> From<()> for OptionsPageInit<'a, A> {
76 fn from(_: ()) -> Self {
77 Self {
78 parent: unsafe { BorrowedContainer::win32(Default::default()) },
79 rx: None,
80 }
81 }
82}
83
84impl<'a, A: PluginApp> OptionsPageInit<'a, A> {
85 pub async fn window<T: OptionsPageComponent<'a, App = A>>(
87 &mut self,
88 sender: &ComponentSender<T>,
89 ) -> Result<Child<View>, Error> {
90 let mut window = Child::<View>::init(self.parent.clone()).await?;
91 self.init(&mut window, sender);
92 Ok(window)
93 }
94
95 pub fn init<T: OptionsPageComponent<'a, App = A>>(
97 &mut self,
98 window: &mut View,
99 sender: &ComponentSender<T>,
100 ) {
101 if let Some(mut rx) = self.rx.take() {
105 let window = window.as_container().as_win32();
106 let sender = sender.clone();
107 winio::compio::runtime::spawn(async move {
108 while let Some(m) = rx.next().await {
111 if let Some(m) = m.try_into(window) {
112 debug!(?m, "Options page message");
113 sender.post(m.into());
114 }
115 }
116 debug!("Options page message channel closed");
117 })
118 .detach();
119 }
120 }
121}
122
123#[allow(unused_must_use)]
127pub fn adjust_window(window: &mut Window) {
128 window.set_style(window.style().unwrap() & !WS_OVERLAPPEDWINDOW);
131
132 window.set_loc(Point::new(0.0, 0.0));
138}