I am having trouble understanding how to create a custom subscription on a page of an iced application which then feeds back to the main application subscription fn.
In the example below the solution is making the application simpler and single page.
For my use case I would have several subscriptions, some pages having multiple, others having one, and others having none. The example below is a simplified version of this.
pub fn main() -> iced::Result {
ProjectGui::run(Settings::default())
}
#[derive(Debug)]
struct ProjectGui {
soft_demo: SoftDemo
}
#[derive(Debug, Clone)]
enum Message {
SoftDemo(SoftDemoMessage),
}
impl Application for ProjectGui {
type Executor = executor::Default;
type Message = Message;
type Theme = Theme;
type Flags = ();
fn new(_flags: ()) -> (Self, Command<Message>) {
Self {
soft_demo: SoftDemo::default(),
}
Command::none()
}
fn title(&self) -> String {
String::from("ProjectGui - Iced")
}
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::SoftDemo(message) => {
self.soft_demo.update(message);
}
Command::none()
}
}
fn view(&self) -> Element<Message> {
// Unrelated
}
fn subscription(&self) -> Subscription<Message> {
// This is where I do not know how to subscribe to subscriptions necessary
// for soft_demo. I have tried:
if self.soft_demo.is_playing {
time::every(Duration::from_millis(1000 / self.soft_demo.speed as u64)).map(Message::SoftDemo(SoftDemoMessage::Tick))
}
// Associated Error:
error[E0308]: mismatched types
--> src\main.rs:241:22
|
241 | .map(Message::SoftDemo(SoftDemoMessage::Tick(Instant::now())))
| --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found enum `Message`
| |
| arguments to this method are incorrect
|
= note: expected fn pointer `fn(std::time::Instant) -> Message`
found enum `Message`
note: associated function defined here
--> C:\Users\workstation.local\.cargo\registry\src\github.com-1ecc6299db9ec823\iced_futures-0.6.0\src\subscription.rs:89:12
|
89 | pub fn map<A>(mut self, f: fn(O) -> A) -> Subscription<H, E, A>
| ^^^
}
#[derive(Debug)]
pub struct SoftDemo {
pub simulation: Simulation,
pub is_playing: bool,
pub queued_ticks: usize,
pub speed: usize,
pub next_speed: Option<usize>,
pub version: usize,
}
#[derive(Debug, Clone)]
pub enum SoftDemoMessage {
Simulation(SimulationMessage, usize),
Tick(Instant),
}
impl<'a> SoftDemo {
pub fn update(&mut self, message: SoftDemoMessage) -> Command<SoftDemoMessage> {
match message {
SoftDemoMessage::Simulation(message, version) => {
if version == self.version {
self.simulation.update(message);
}
},
SoftDemoMessage::Tick(_) | SoftDemoMessage::Next => {
self.queued_ticks = (self.queued_ticks + 1).min(self.speed);
if let Some(task) = self.simulation.tick(self.queued_ticks) {
if let Some(speed) = self.next_speed.take() {
self.speed = speed;
}
self.queued_ticks = 0;
let version = self.version;
return Command::perform(task, move |message| {
SoftDemoMessage::Simulation(message, version)
});
}
},
}
Command::none()
}
// This is where I need to be creating a custom subscription that the
// fn subscription() in the impl ProjectGui {} can subscribe to
// pub fn subscription(&self) -> Subscription<SoftDemoMessage> {
// if self.is_playing {
// time::every(Duration::from_millis(1000 / self.speed as u64))
// .map(SoftDemoMessage::Tick)
// } else {
// Subscription::none()
// }
// }
}
// If you need the Simulation and SimulationMessage, struct/enum, I can include
// If you need a fully functioning body of code then try to merge the two code bases below to achieve the same objective
Iced Gui Examples:
Tour (I need a gui with multiple pages)
Game_of_Life (I need a canvas running a simulation with a tick subscription on one page of pages: Vec)
Download_Progress (Best example I could find for creating a custom subscription but I cannot seem to wrap my head around how this is working)