Alright, after a bit more digging, I got it figured out. Based on this post and the example given, here is a bare minimum example as I described as wanting in the above post:
use iced::widget::{button, column, text};
use iced::{Element, Size, Subscription, Task, window};
use std::collections::BTreeMap;
#[derive(Debug, Clone, PartialEq)]
pub enum WindowType {
MainWindow,
SecondWindow,
}
impl WindowType {
pub fn settings(&self) -> window::Settings {
match self {
WindowType::MainWindow => window::Settings {
size: Size::new(400.0, 400.0),
..window::Settings::default()
},
WindowType::SecondWindow => window::Settings {
size: Size::new(200.0, 200.0),
..window::Settings::default()
},
}
}
}
#[derive(Debug, Clone)]
pub enum MainWindowMessage {
CreateSecondWindow,
}
#[derive(Debug, Clone)]
pub enum SecondWindowMessage {
Hello,
}
#[derive(Debug, Clone)]
pub enum Message {
WindowOpened(window::Id, WindowType),
WindowClosed(window::Id),
MainWindow(MainWindowMessage),
SecondWindow(SecondWindowMessage),
}
struct App {
windows: BTreeMap<window::Id, WindowType>,
}
impl App {
fn new() -> (Self, Task<Message>) {
let window_type = WindowType::MainWindow;
let (_new_id, task) = window::open(window_type.settings());
(
Self {
windows: BTreeMap::new(),
},
task.map(move |id| Message::WindowOpened(id, window_type.clone())),
)
}
fn title(&self, id: window::Id) -> String {
if let Some(window_type) = self.windows.get(&id) {
match window_type {
WindowType::MainWindow => "main window".to_string(),
WindowType::SecondWindow => "second window".to_string(),
}
} else {
"invalid window".to_string()
}
}
fn update(&mut self, message: Message) -> Task<Message> {
match message {
Message::WindowOpened(new_window_id, new_window_type) => {
self.windows.insert(new_window_id, new_window_type);
}
Message::WindowClosed(id) => {
self.windows.remove(&id);
if self.windows.is_empty() {
return iced::exit();
}
}
Message::MainWindow(main_window_message) => match main_window_message {
MainWindowMessage::CreateSecondWindow => {
let new_window_type = WindowType::SecondWindow;
// if the window type already exists, do not create a new window and focus the existing one
for (window_id, window_type) in &self.windows {
if new_window_type == *window_type {
return window::gain_focus(*window_id);
}
}
let (_new_id, task) = window::open(new_window_type.settings());
return task.map(move |id| Message::WindowOpened(id, new_window_type.clone()));
}
},
Message::SecondWindow(second_window_message) => match second_window_message {
SecondWindowMessage::Hello => {
println!("hello!");
}
},
}
Task::none()
}
fn view(&'_ self, id: window::Id) -> Element<'_, Message> {
if let Some(window_type) = self.windows.get(&id) {
match window_type {
WindowType::MainWindow => column![
button("launch second window")
.on_press(Message::MainWindow(MainWindowMessage::CreateSecondWindow))
]
.into(),
WindowType::SecondWindow => column![
text("the second window"),
button("hello").on_press(Message::SecondWindow(SecondWindowMessage::Hello))
]
.into(),
}
} else {
column![].into()
}
}
fn subscription(&self) -> Subscription<Message> {
window::close_events().map(Message::WindowClosed)
}
}
pub fn main() -> iced::Result {
iced::daemon(App::title, App::update, App::view)
.subscription(App::subscription)
.run_with(App::new)
}