-
Hi, I just started building out a small application in iced, but am struggling to modularise my code to avoid monolithic
enum App {
Loading,
Uninitialised(app::uninitialised::Data),
Initialised(app::initialised::Data),
}
impl iced::Application for App {
type Executor = iced::executor::Default;
type Message = Message;
type Flags = ();
fn new(_flags: Self::Flags) -> (Self, Command<Self::Message>) {
todo!();
}
fn title(&self) -> String {
String::from("App")
}
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
match self {
App::Loading => app::loading::update(self, message),
App::Uninitialised(data) => app::uninitialised::update(self, data, message),
App::Initialised(data) => app::initialised::update(self, data, message),
}
}
fn view(&mut self) -> Element<Self::Message> {
match self {
App::Loading => app::loading::view(self),
App::Uninitialised(data) => app::uninitialised::view(self, data),
App::Initialised(data) => app::initialised::view(self, data),
}
}
} As you can see my general structure is to separate my view and update functions for each of the App's overarching states. However, this doesn't compile as both self and data are borrowed mutably. I could technically overcome this by doing something like so in each function: // in app::uninitialised
pub fn update(app: &mut App, data: &Data, message: Message) -> Command<Message> {
let data = match app {
App::Uninitialised(data) => data,
_ => panic!("incorrect app state),
}
} but this is obviously less than ideal. Are there any common ways to organise iced projects? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
This structure is just fine! If you remove If you're wanting to update // in app::uninitialised
// uninitialized related messages
pub enum Message {
..
}
// events that need to be handled by parent
pub enum Event {
..
}
// state
pub struct Data {
..
}
pub fn update(data: &mut Data, message: Message) -> Option<Event> {
match message {
..
}
} // in app
enum Message {
Loading(Message),
Uninitialized(Message),
Initialized(Message),
}
impl iced::Application for App {
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
match (self, message) {
(App::Uninitialized(data), Message::Uninitialized(message)) => {
if let Some(event) = app::uninitialized::update(data, message) {
match event {
..
}
}
}
..
}
}
fn view(&mut self) -> Element<Self::Message> {
match self {
App::Loading => app::loading::view().map(Message::Loading),
App::Uninitialized(data) => app::uninitialized::view(data).map(Message::Uninitialized),
App::Initialized(data) => app::initialized::view(data).map(Message::Initialized),
}
}
} |
Beta Was this translation helpful? Give feedback.
This structure is just fine! If you remove
&mut App
from theview
/update
functions of each module, you'll no longer run into the issue. Those modules don't need to depend onApp
and shouldn't be aware of it anyways (circular dependency). Is there a reason you were trying to passApp
down into those modules?If you're wanting to update
App
within each, you'd be better off havingupdate
from each module return anOption<Event>
that you can use in the parent module to update it's state. You can also defineMessage
for each module and map that into the parentMessage
, see below.