1use iced::application;
8use iced::window;
9use iced::{
10 self, Program,
11 program::{self, with_style, with_subscription, with_theme, with_title},
12 runtime::{Appearance, DefaultStyle},
13};
14use iced::{Element, Result, Settings, Subscription, Task};
15
16use std::marker::PhantomData;
17
18pub(crate) struct Instance<State, Message, Theme, Renderer, Update, View, Executor> {
19 update: Update,
20 view: View,
21 _state: PhantomData<State>,
22 _message: PhantomData<Message>,
23 _theme: PhantomData<Theme>,
24 _renderer: PhantomData<Renderer>,
25 _executor: PhantomData<Executor>,
26}
27
28pub fn multi_window<State, Message, Theme, Renderer, Executor>(
30 title: impl Title<State>,
31 update: impl application::Update<State, Message>,
32 view: impl for<'a> self::View<'a, State, Message, Theme, Renderer>,
33) -> MultiWindow<impl Program<State = State, Message = Message, Theme = Theme>>
34where
35 State: 'static,
36 Message: Send + std::fmt::Debug + 'static,
37 Theme: Default + DefaultStyle,
38 Renderer: program::Renderer,
39 Executor: iced::Executor,
40{
41 use std::marker::PhantomData;
42
43 impl<State, Message, Theme, Renderer, Update, View, Executor> Program
44 for Instance<State, Message, Theme, Renderer, Update, View, Executor>
45 where
46 Message: Send + std::fmt::Debug + 'static,
47 Theme: Default + DefaultStyle,
48 Renderer: program::Renderer,
49 Update: application::Update<State, Message>,
50 View: for<'a> self::View<'a, State, Message, Theme, Renderer>,
51 Executor: iced::Executor,
52 {
53 type State = State;
54 type Message = Message;
55 type Theme = Theme;
56 type Renderer = Renderer;
57 type Executor = Executor;
58
59 fn update(&self, state: &mut Self::State, message: Self::Message) -> Task<Self::Message> {
60 self.update.update(state, message).into()
61 }
62
63 fn view<'a>(
64 &self,
65 state: &'a Self::State,
66 window: window::Id,
67 ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
68 self.view.view(state, window).into()
69 }
70 }
71
72 MultiWindow {
73 raw: Instance {
74 update,
75 view,
76 _state: PhantomData,
77 _message: PhantomData,
78 _theme: PhantomData,
79 _renderer: PhantomData,
80 _executor: PhantomData::<Executor>,
81 },
82 settings: Settings::default(),
83 window: None,
84 }
85 .title(title)
86}
87
88#[derive(Debug)]
96pub struct MultiWindow<P: Program> {
97 raw: P,
98 settings: Settings,
99 window: Option<window::Settings>,
100}
101
102impl<P: Program> MultiWindow<P> {
103 #[cfg(any(feature = "winit", feature = "wayland"))]
104 pub fn run(self) -> Result
112 where
113 Self: 'static,
114 P::State: Default,
115 {
116 self.raw.run(self.settings, self.window)
117 }
118
119 #[cfg(any(feature = "winit", feature = "wayland"))]
120 pub fn run_with<I>(self, initialize: I) -> Result
122 where
123 Self: 'static,
124 I: FnOnce() -> (P::State, Task<P::Message>) + 'static,
125 {
126 self.raw.run_with(self.settings, self.window, initialize)
127 }
128
129 pub fn settings(self, settings: Settings) -> Self {
131 Self { settings, ..self }
132 }
133
134 pub(crate) fn title(
136 self,
137 title: impl Title<P::State>,
138 ) -> MultiWindow<impl Program<State = P::State, Message = P::Message, Theme = P::Theme>> {
139 MultiWindow {
140 raw: with_title(self.raw, move |state, window| title.title(state, window)),
141 settings: self.settings,
142 window: self.window,
143 }
144 }
145
146 pub fn subscription(
148 self,
149 f: impl Fn(&P::State) -> Subscription<P::Message>,
150 ) -> MultiWindow<impl Program<State = P::State, Message = P::Message, Theme = P::Theme>> {
151 MultiWindow {
152 raw: with_subscription(self.raw, f),
153 settings: self.settings,
154 window: self.window,
155 }
156 }
157
158 pub fn theme(
160 self,
161 f: impl Fn(&P::State, window::Id) -> P::Theme,
162 ) -> MultiWindow<impl Program<State = P::State, Message = P::Message, Theme = P::Theme>> {
163 MultiWindow {
164 raw: with_theme(self.raw, f),
165 settings: self.settings,
166 window: self.window,
167 }
168 }
169
170 pub fn style(
172 self,
173 f: impl Fn(&P::State, &P::Theme) -> Appearance,
174 ) -> MultiWindow<impl Program<State = P::State, Message = P::Message, Theme = P::Theme>> {
175 MultiWindow {
176 raw: with_style(self.raw, f),
177 settings: self.settings,
178 window: self.window,
179 }
180 }
181
182 pub fn window(self, window: window::Settings) -> Self {
184 Self {
185 raw: self.raw,
186 settings: self.settings,
187 window: Some(window),
188 }
189 }
190}
191
192pub trait Title<State> {
199 fn title(&self, state: &State, window: window::Id) -> String;
201}
202
203impl<State> Title<State> for &'static str {
204 fn title(&self, _state: &State, _window: window::Id) -> String {
205 (*self).to_string()
206 }
207}
208
209impl<T, State> Title<State> for T
210where
211 T: Fn(&State, window::Id) -> String,
212{
213 fn title(&self, state: &State, window: window::Id) -> String {
214 self(state, window)
215 }
216}
217
218pub trait View<'a, State, Message, Theme, Renderer> {
223 fn view(
225 &self,
226 state: &'a State,
227 window: window::Id,
228 ) -> impl Into<Element<'a, Message, Theme, Renderer>>;
229}
230
231impl<'a, T, State, Message, Theme, Renderer, Widget> View<'a, State, Message, Theme, Renderer> for T
232where
233 T: Fn(&'a State, window::Id) -> Widget,
234 State: 'static,
235 Widget: Into<Element<'a, Message, Theme, Renderer>>,
236{
237 fn view(
238 &self,
239 state: &'a State,
240 window: window::Id,
241 ) -> impl Into<Element<'a, Message, Theme, Renderer>> {
242 self(state, window)
243 }
244}