nice_plug_iced/application/
timed.rs1use std::sync::{Arc, Mutex};
4
5use crate::{EditorState, NiceGuiContext, iced};
6
7use iced::program::{self, Program};
8use iced::theme;
9use iced::time::Instant;
10use iced::window;
11use iced::{Element, Settings, Subscription, Task};
12
13use iced_debug as debug;
14
15use super::{Application, BootFn, ViewFn};
16
17pub fn timed<State, EState, Message, Theme, Renderer>(
29 editor_state: EditorState<EState>,
30 nice_ctx: NiceGuiContext,
31 boot: impl BootFn<State, EState, Message>,
32 update: impl UpdateFn<State, Message>,
33 subscription: impl Fn(&State) -> Subscription<Message>,
34 view: impl for<'a> ViewFn<'a, State, Message, Theme, Renderer>,
35) -> Application<impl Program<State = State, Message = (Message, Instant), Theme = Theme>>
36where
37 State: 'static,
38 EState: Send + 'static,
39 Message: Send + 'static,
40 Theme: theme::Base + 'static,
41 Renderer: program::Renderer + 'static,
42{
43 use std::marker::PhantomData;
44
45 struct Instance<State, EState, Message, Theme, Renderer, Boot, Update, Subscription, View> {
46 nice_ctx: NiceGuiContext,
47 editor_state: Arc<Mutex<Option<EState>>>,
48 boot: Boot,
49 update: Update,
50 subscription: Subscription,
51 view: View,
52 _state: PhantomData<State>,
53 _message: PhantomData<Message>,
54 _theme: PhantomData<Theme>,
55 _renderer: PhantomData<Renderer>,
56 }
57
58 impl<State, EState, Message, Theme, Renderer, Boot, Update, Subscription, View> Program
59 for Instance<State, EState, Message, Theme, Renderer, Boot, Update, Subscription, View>
60 where
61 EState: Send + 'static,
62 Message: Send + 'static,
63 Theme: theme::Base + 'static,
64 Renderer: program::Renderer + 'static,
65 Boot: self::BootFn<State, EState, Message>,
66 Update: self::UpdateFn<State, Message>,
67 Subscription: Fn(&State) -> self::Subscription<Message>,
68 View: for<'a> self::ViewFn<'a, State, Message, Theme, Renderer>,
69 {
70 type State = State;
71 type Message = (Message, Instant);
72 type Theme = Theme;
73 type Renderer = Renderer;
74 type Executor = iced_futures::backend::default::Executor;
75
76 fn name() -> &'static str {
77 let name = std::any::type_name::<State>();
78
79 name.split("::").next().unwrap_or("a_cool_application")
80 }
81
82 fn settings(&self) -> Settings {
83 Settings::default()
84 }
85
86 fn window(&self) -> Option<iced::core::window::Settings> {
87 Some(window::Settings::default())
88 }
89
90 fn boot(&self) -> (State, Task<Self::Message>) {
91 let editor_state = EditorState::from_shared(&self.editor_state);
92
93 let (state, task) = self.boot.boot(editor_state, self.nice_ctx.clone());
94
95 (state, task.map(|message| (message, Instant::now())))
96 }
97
98 fn update(
99 &self,
100 state: &mut Self::State,
101 (message, now): Self::Message,
102 ) -> Task<Self::Message> {
103 debug::hot(move || {
104 self.update
105 .update(state, message, now)
106 .into()
107 .map(|message| (message, Instant::now()))
108 })
109 }
110
111 fn view<'a>(
112 &self,
113 state: &'a Self::State,
114 _window: window::Id,
115 ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
116 debug::hot(|| {
117 self.view
118 .view(state)
119 .map(|message| (message, Instant::now()))
120 })
121 }
122
123 fn subscription(&self, state: &Self::State) -> self::Subscription<Self::Message> {
124 debug::hot(|| (self.subscription)(state).map(|message| (message, Instant::now())))
125 }
126 }
127
128 Application {
129 raw: Instance {
130 nice_ctx,
131 editor_state: editor_state.into_shared(),
132 boot,
133 update,
134 subscription,
135 view,
136 _state: PhantomData,
137 _message: PhantomData,
138 _theme: PhantomData,
139 _renderer: PhantomData,
140 },
141 iced_settings: Settings::default(),
142 presets: Vec::new(),
143 }
144}
145
146pub trait UpdateFn<State, Message> {
151 fn update(&self, state: &mut State, message: Message, now: Instant)
153 -> impl Into<Task<Message>>;
154}
155
156impl<State, Message> UpdateFn<State, Message> for () {
157 fn update(
158 &self,
159 _state: &mut State,
160 _message: Message,
161 _now: Instant,
162 ) -> impl Into<Task<Message>> {
163 }
164}
165
166impl<T, State, Message, C> UpdateFn<State, Message> for T
167where
168 T: Fn(&mut State, Message, Instant) -> C,
169 C: Into<Task<Message>>,
170{
171 fn update(
172 &self,
173 state: &mut State,
174 message: Message,
175 now: Instant,
176 ) -> impl Into<Task<Message>> {
177 self(state, message, now)
178 }
179}