Skip to content

Commit c1990d7

Browse files
authored
Introduce PageMessage type (#164)
1 parent 22c4ff5 commit c1990d7

File tree

7 files changed

+129
-86
lines changed

7 files changed

+129
-86
lines changed

neothesia/src/iced_utils/iced_state.rs

+1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ where
103103
}
104104

105105
/// Returns whether the event queue of the [`State`] is empty or not.
106+
#[allow(dead_code)]
106107
pub fn is_queue_empty(&self) -> bool {
107108
self.queued_events.is_empty() && self.queued_messages.is_empty()
108109
}

neothesia/src/scene/menu_scene/iced_menu/exit.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use iced_core::{Alignment, Length};
2-
use iced_runtime::Command;
32
use iced_widget::{column as col, row};
43
use neothesia_iced_widgets::{Element, NeoBtn};
54

65
use crate::{context::Context, NeothesiaEvent};
76

8-
use super::{center_x, centered_text, Data, Message, Page};
7+
use super::{center_x, centered_text, page::PageMessage, Data, Message, Page};
98

109
pub struct ExitPage;
1110

@@ -18,17 +17,17 @@ pub enum Event {
1817
impl Page for ExitPage {
1918
type Event = Event;
2019

21-
fn update(_data: &mut Data, event: Event, ctx: &mut Context) -> Command<Message> {
20+
fn update(_data: &mut Data, event: Event, ctx: &mut Context) -> PageMessage {
2221
match event {
2322
Event::GoBack => {
24-
return Command::perform(async {}, |_| Message::GoBack);
23+
return PageMessage::go_back();
2524
}
2625
Event::Exit => {
2726
ctx.proxy.send_event(NeothesiaEvent::Exit).ok();
2827
}
2928
}
3029

31-
Command::none()
30+
PageMessage::None
3231
}
3332

3433
fn view<'a>(_data: &'a Data, _ctx: &Context) -> Element<'a, Event> {

neothesia/src/scene/menu_scene/iced_menu/main.rs

+48-44
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ use neothesia_iced_widgets::{BarLayout, Layout, NeoBtn};
1010

1111
use crate::{context::Context, scene::menu_scene::icons, song::Song};
1212

13-
use super::{page::Page, top_padded, Data, Message, Step};
13+
use super::{
14+
page::{Page, PageMessage},
15+
top_padded, Data, Message, Step,
16+
};
1417

1518
#[derive(Debug, Clone)]
1619
pub enum Event {
@@ -24,20 +27,24 @@ pub struct MainPage;
2427
impl Page for MainPage {
2528
type Event = Event;
2629

27-
fn update(data: &mut Data, msg: Self::Event, ctx: &mut Context) -> Command<Message> {
30+
fn update(data: &mut Data, msg: Self::Event, ctx: &mut Context) -> PageMessage {
2831
match msg {
2932
Event::Play => {
3033
super::play(data, ctx);
3134
}
3235
Event::GoToPage(step) => {
33-
return Command::perform(async {}, move |_| Message::GoToPage(step));
36+
return PageMessage::go_to_page(step);
3437
}
3538
Event::MidiFilePicker(msg) => {
36-
return midi_file_picker_update(data, msg, ctx);
39+
return PageMessage::Command(
40+
midi_file_picker_update(data, msg, ctx)
41+
.map(Event::MidiFilePicker)
42+
.map(Message::MainPage),
43+
);
3744
}
3845
};
3946

40-
Command::none()
47+
PageMessage::None
4148
}
4249

4350
fn view<'a>(data: &'a Data, ctx: &Context) -> neothesia_iced_widgets::Element<'a, Self::Event> {
@@ -154,19 +161,23 @@ impl MidiFilePickerMessage {
154161

155162
impl From<MidiFilePickerMessage> for Message {
156163
fn from(msg: MidiFilePickerMessage) -> Self {
157-
Message::MainPage(super::main::Event::MidiFilePicker(msg))
164+
Message::MainPage(Event::MidiFilePicker(msg))
158165
}
159166
}
160167

161168
fn midi_file_picker_update(
162169
data: &mut Data,
163170
msg: MidiFilePickerMessage,
164171
ctx: &mut Context,
165-
) -> Command<Message> {
172+
) -> Command<MidiFilePickerMessage> {
166173
match msg {
167174
MidiFilePickerMessage::OpenMidiFilePicker => {
168175
data.is_loading = true;
169-
return open_midi_file_picker(|v| MidiFilePickerMessage::MidiFileLoaded(v).into());
176+
177+
return Command::perform(
178+
open_midi_file_picker(),
179+
MidiFilePickerMessage::MidiFileLoaded,
180+
);
170181
}
171182
MidiFilePickerMessage::MidiFileLoaded(midi) => {
172183
if let Some((midi, path)) = midi {
@@ -180,41 +191,34 @@ fn midi_file_picker_update(
180191
Command::none()
181192
}
182193

183-
fn open_midi_file_picker(
184-
f: impl FnOnce(Option<(midi_file::MidiFile, PathBuf)>) -> Message + 'static + Send,
185-
) -> Command<Message> {
186-
Command::perform(
187-
async {
188-
let file = rfd::AsyncFileDialog::new()
189-
.add_filter("midi", &["mid", "midi"])
190-
.pick_file()
191-
.await;
192-
193-
if let Some(file) = file {
194-
log::info!("File path = {:?}", file.path());
195-
196-
let thread = async_thread::Builder::new()
197-
.name("midi-loader".into())
198-
.spawn(move || {
199-
let midi = midi_file::MidiFile::new(file.path());
200-
201-
if let Err(e) = &midi {
202-
log::error!("{}", e);
203-
}
204-
205-
midi.map(|midi| (midi, file.path().to_path_buf())).ok()
206-
});
207-
208-
if let Ok(thread) = thread {
209-
thread.join().await.ok().flatten()
210-
} else {
211-
None
194+
async fn open_midi_file_picker() -> Option<(midi_file::MidiFile, PathBuf)> {
195+
let file = rfd::AsyncFileDialog::new()
196+
.add_filter("midi", &["mid", "midi"])
197+
.pick_file()
198+
.await;
199+
200+
if let Some(file) = file {
201+
log::info!("File path = {:?}", file.path());
202+
203+
let thread = async_thread::Builder::new()
204+
.name("midi-loader".into())
205+
.spawn(move || {
206+
let midi = midi_file::MidiFile::new(file.path());
207+
208+
if let Err(e) = &midi {
209+
log::error!("{}", e);
212210
}
213-
} else {
214-
log::info!("User canceled dialog");
215-
None
216-
}
217-
},
218-
f,
219-
)
211+
212+
midi.map(|midi| (midi, file.path().to_path_buf())).ok()
213+
});
214+
215+
if let Ok(thread) = thread {
216+
thread.join().await.ok().flatten()
217+
} else {
218+
None
219+
}
220+
} else {
221+
log::info!("User canceled dialog");
222+
None
223+
}
220224
}

neothesia/src/scene/menu_scene/iced_menu/mod.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::collections::VecDeque;
22

3+
use self::page::PageMessage;
4+
35
use super::Renderer;
46
use iced_core::{
57
alignment::{Horizontal, Vertical},
@@ -100,6 +102,14 @@ impl AppUi {
100102
}
101103
}
102104
}
105+
106+
fn handle_page_msg(&mut self, ctx: &mut Context, msg: PageMessage) -> Command<Message> {
107+
match msg {
108+
PageMessage::Message(msg) => self.update(ctx, msg),
109+
PageMessage::Command(cmd) => cmd,
110+
PageMessage::None => Command::none(),
111+
}
112+
}
103113
}
104114

105115
impl Program for AppUi {
@@ -114,16 +124,20 @@ impl Program for AppUi {
114124
self.go_back();
115125
}
116126
Message::MainPage(msg) => {
117-
return MainPage::update(&mut self.data, msg, ctx);
127+
let msg = MainPage::update(&mut self.data, msg, ctx);
128+
return self.handle_page_msg(ctx, msg);
118129
}
119130
Message::SettingsPage(msg) => {
120-
return SettingsPage::update(&mut self.data, msg, ctx);
131+
let msg = SettingsPage::update(&mut self.data, msg, ctx);
132+
return self.handle_page_msg(ctx, msg);
121133
}
122134
Message::TracksPage(msg) => {
123-
return TracksPage::update(&mut self.data, msg, ctx);
135+
let msg = TracksPage::update(&mut self.data, msg, ctx);
136+
return self.handle_page_msg(ctx, msg);
124137
}
125138
Message::ExitPage(msg) => {
126-
return ExitPage::update(&mut self.data, msg, ctx);
139+
let msg = ExitPage::update(&mut self.data, msg, ctx);
140+
return self.handle_page_msg(ctx, msg);
127141
}
128142
}
129143

neothesia/src/scene/menu_scene/iced_menu/page.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,35 @@ use neothesia_iced_widgets::Element;
33

44
use crate::context::Context;
55

6-
use super::{Data, Message};
6+
use super::{Data, Message, Step};
7+
8+
pub enum PageMessage {
9+
Message(Message),
10+
Command(Command<Message>),
11+
None,
12+
}
13+
14+
impl PageMessage {
15+
pub fn go_back() -> Self {
16+
Self::message(Message::GoBack)
17+
}
18+
19+
pub fn go_to_page(step: Step) -> Self {
20+
Self::message(Message::GoToPage(step))
21+
}
22+
23+
pub fn none() -> Self {
24+
Self::None
25+
}
26+
27+
fn message(msg: Message) -> Self {
28+
Self::Message(msg)
29+
}
30+
}
731

832
pub trait Page {
933
type Event;
10-
fn update(data: &mut Data, msg: Self::Event, ctx: &mut Context) -> Command<Message>;
34+
fn update(data: &mut Data, msg: Self::Event, ctx: &mut Context) -> PageMessage;
1135
fn view<'a>(data: &'a Data, ctx: &Context) -> Element<'a, Self::Event>;
1236
fn keyboard_input(event: &iced_runtime::keyboard::Event, ctx: &Context) -> Option<Message>;
1337
}

neothesia/src/scene/menu_scene/iced_menu/settings.rs

+24-26
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ use neothesia_iced_widgets::{ActionRow, BarLayout, Element, Layout, NeoBtn, Pref
1010

1111
use crate::{context::Context, output_manager::OutputDescriptor, scene::menu_scene::icons};
1212

13-
use super::{centered_text, page::Page, theme, Data, InputDescriptor, Message};
13+
use super::{
14+
centered_text,
15+
page::{Page, PageMessage},
16+
theme, Data, InputDescriptor, Message,
17+
};
1418

1519
#[derive(Debug, Clone)]
1620
pub enum RangeUpdateKind {
@@ -44,7 +48,7 @@ impl SettingsPage {
4448
impl Page for SettingsPage {
4549
type Event = Event;
4650

47-
fn update(data: &mut Data, msg: Event, ctx: &mut Context) -> Command<Message> {
51+
fn update(data: &mut Data, msg: Event, ctx: &mut Context) -> PageMessage {
4852
match msg {
4953
Event::SelectOutput(output) => {
5054
ctx.config
@@ -67,9 +71,10 @@ impl Page for SettingsPage {
6771
}
6872
Event::OpenSoundFontPicker => {
6973
data.is_loading = true;
70-
return open_sound_font_picker(|res| {
71-
Message::SettingsPage(Event::SoundFontFileLoaded(res))
72-
});
74+
75+
let cmd = Command::perform(open_sound_font_picker(), Event::SoundFontFileLoaded)
76+
.map(Message::SettingsPage);
77+
return PageMessage::Command(cmd);
7378
}
7479
Event::SoundFontFileLoaded(font) => {
7580
if let Some(font) = font {
@@ -100,11 +105,11 @@ impl Page for SettingsPage {
100105
}
101106
},
102107
Event::GoBack => {
103-
return Command::perform(async {}, |_| Message::GoBack);
108+
return PageMessage::go_back();
104109
}
105110
}
106111

107-
Command::none()
112+
PageMessage::none()
108113
}
109114

110115
fn view<'a>(data: &'a Data, ctx: &Context) -> Element<'a, Event> {
@@ -308,24 +313,17 @@ fn guidelines_group<'a>(_data: &'a Data, ctx: &Context) -> Element<'a, Event> {
308313
.build()
309314
}
310315

311-
fn open_sound_font_picker(
312-
f: impl FnOnce(Option<PathBuf>) -> Message + 'static + Send,
313-
) -> Command<Message> {
314-
Command::perform(
315-
async {
316-
let file = rfd::AsyncFileDialog::new()
317-
.add_filter("SoundFont2", &["sf2"])
318-
.pick_file()
319-
.await;
320-
321-
if let Some(file) = file.as_ref() {
322-
log::info!("Font path = {:?}", file.path());
323-
} else {
324-
log::info!("User canceled dialog");
325-
}
316+
async fn open_sound_font_picker() -> Option<PathBuf> {
317+
let file = rfd::AsyncFileDialog::new()
318+
.add_filter("SoundFont2", &["sf2"])
319+
.pick_file()
320+
.await;
326321

327-
file.map(|f| f.path().to_owned())
328-
},
329-
f,
330-
)
322+
if let Some(file) = file.as_ref() {
323+
log::info!("Font path = {:?}", file.path());
324+
} else {
325+
log::info!("User canceled dialog");
326+
}
327+
328+
file.map(|f| f.path().to_owned())
331329
}

neothesia/src/scene/menu_scene/iced_menu/tracks.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ use iced_core::{
22
alignment::{Horizontal, Vertical},
33
Alignment, Length, Padding,
44
};
5-
use iced_runtime::Command;
65
use iced_widget::{button, column as col, container, row, vertical_space};
76

87
use crate::{context::Context, scene::menu_scene::icons, song::PlayerConfig};
98
use neothesia_iced_widgets::{BarLayout, Element, Layout, NeoBtn};
109

11-
use super::{centered_text, page::Page, theme, Data, Message};
10+
use super::{
11+
centered_text,
12+
page::{Page, PageMessage},
13+
theme, Data, Message,
14+
};
1215

1316
#[derive(Debug, Clone)]
1417
pub enum Event {
@@ -24,7 +27,7 @@ pub struct TracksPage;
2427
impl Page for TracksPage {
2528
type Event = Event;
2629

27-
fn update(data: &mut Data, event: Event, ctx: &mut Context) -> Command<Message> {
30+
fn update(data: &mut Data, event: Event, ctx: &mut Context) -> PageMessage {
2831
match event {
2932
Event::AllTracksPlayer(config) => {
3033
if let Some(song) = ctx.song.as_mut() {
@@ -44,14 +47,14 @@ impl Page for TracksPage {
4447
}
4548
}
4649
Event::GoBack => {
47-
return Command::perform(async {}, |_| Message::GoBack);
50+
return PageMessage::go_back();
4851
}
4952
Event::Play => {
5053
super::play(data, ctx);
5154
}
5255
}
5356

54-
Command::none()
57+
PageMessage::none()
5558
}
5659

5760
fn view<'a>(_data: &'a Data, ctx: &Context) -> Element<'a, Event> {

0 commit comments

Comments
 (0)