Use Task chaining to simplify multi_window example

This commit is contained in:
Héctor Ramón Jiménez 2024-06-14 03:04:51 +02:00
parent b21e4567dc
commit 88b9384402
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
4 changed files with 107 additions and 96 deletions

View file

@ -1,16 +1,15 @@
use iced::event;
use iced::executor;
use iced::multi_window::{self, Application};
use iced::widget::{
button, center, column, container, scrollable, text, text_input,
button, center, column, container, horizontal_space, scrollable, text,
text_input,
};
use iced::window;
use iced::{
Alignment, Element, Length, Point, Settings, Subscription, Task, Theme,
Vector,
Alignment, Element, Length, Settings, Subscription, Task, Theme, Vector,
};
use std::collections::HashMap;
use std::collections::BTreeMap;
fn main() -> iced::Result {
Example::run(Settings::default())
@ -18,8 +17,7 @@ fn main() -> iced::Result {
#[derive(Default)]
struct Example {
windows: HashMap<window::Id, Window>,
next_window_pos: window::Position,
windows: BTreeMap<window::Id, Window>,
}
#[derive(Debug)]
@ -33,13 +31,12 @@ struct Window {
#[derive(Debug, Clone)]
enum Message {
OpenWindow,
WindowOpened(window::Id),
WindowClosed(window::Id),
ScaleInputChanged(window::Id, String),
ScaleChanged(window::Id, String),
TitleChanged(window::Id, String),
CloseWindow(window::Id),
WindowOpened(window::Id, Option<Point>),
WindowClosed(window::Id),
NewWindow,
}
impl multi_window::Application for Example {
@ -51,8 +48,7 @@ impl multi_window::Application for Example {
fn new(_flags: ()) -> (Self, Task<Message>) {
(
Example {
windows: HashMap::from([(window::Id::MAIN, Window::new(1))]),
next_window_pos: window::Position::Default,
windows: BTreeMap::from([(window::Id::MAIN, Window::new(1))]),
},
Task::none(),
)
@ -62,48 +58,36 @@ impl multi_window::Application for Example {
self.windows
.get(&window)
.map(|window| window.title.clone())
.unwrap_or("Example".to_string())
.unwrap_or_default()
}
fn update(&mut self, message: Message) -> Task<Message> {
match message {
Message::ScaleInputChanged(id, scale) => {
let window =
self.windows.get_mut(&id).expect("Window not found!");
window.scale_input = scale;
Message::OpenWindow => {
let Some(last_window) = self.windows.keys().last() else {
return Task::none();
};
Task::none()
window::fetch_position(*last_window)
.then(|last_position| {
let position = last_position.map_or(
window::Position::Default,
|last_position| {
window::Position::Specific(
last_position + Vector::new(20.0, 20.0),
)
},
);
window::open(window::Settings {
position,
..window::Settings::default()
})
})
.map(Message::WindowOpened)
}
Message::ScaleChanged(id, scale) => {
let window =
self.windows.get_mut(&id).expect("Window not found!");
window.current_scale = scale
.parse::<f64>()
.unwrap_or(window.current_scale)
.clamp(0.5, 5.0);
Task::none()
}
Message::TitleChanged(id, title) => {
let window =
self.windows.get_mut(&id).expect("Window not found.");
window.title = title;
Task::none()
}
Message::CloseWindow(id) => window::close(id),
Message::WindowClosed(id) => {
self.windows.remove(&id);
Task::none()
}
Message::WindowOpened(id, position) => {
if let Some(position) = position {
self.next_window_pos = window::Position::Specific(
position + Vector::new(20.0, 20.0),
);
}
Message::WindowOpened(id) => {
self.windows.insert(id, Window::new(self.windows.len() + 1));
if let Some(window) = self.windows.get(&id) {
text_input::focus(window.input_id.clone())
@ -111,30 +95,52 @@ impl multi_window::Application for Example {
Task::none()
}
}
Message::NewWindow => {
let count = self.windows.len() + 1;
Message::WindowClosed(id) => {
self.windows.remove(&id);
let (id, spawn_window) = window::open(window::Settings {
position: self.next_window_pos,
exit_on_close_request: count % 2 == 0,
..Default::default()
});
Task::none()
}
Message::ScaleInputChanged(id, scale) => {
if let Some(window) = self.windows.get_mut(&id) {
window.scale_input = scale;
}
self.windows.insert(id, Window::new(count));
Task::none()
}
Message::ScaleChanged(id, scale) => {
if let Some(window) = self.windows.get_mut(&id) {
window.current_scale = scale
.parse::<f64>()
.unwrap_or(window.current_scale)
.clamp(0.5, 5.0);
}
spawn_window
Task::none()
}
Message::TitleChanged(id, title) => {
if let Some(window) = self.windows.get_mut(&id) {
window.title = title;
}
Task::none()
}
}
}
fn view(&self, window: window::Id) -> Element<Message> {
let content = self.windows.get(&window).unwrap().view(window);
center(content).into()
fn view(&self, window_id: window::Id) -> Element<Message> {
if let Some(window) = self.windows.get(&window_id) {
center(window.view(window_id)).into()
} else {
horizontal_space().into()
}
}
fn theme(&self, window: window::Id) -> Self::Theme {
self.windows.get(&window).unwrap().theme.clone()
fn theme(&self, window: window::Id) -> Theme {
if let Some(window) = self.windows.get(&window) {
window.theme.clone()
} else {
Theme::default()
}
}
fn scale_factor(&self, window: window::Id) -> f64 {
@ -145,24 +151,7 @@ impl multi_window::Application for Example {
}
fn subscription(&self) -> Subscription<Self::Message> {
event::listen_with(|event, _, window| {
if let iced::Event::Window(window_event) = event {
match window_event {
window::Event::CloseRequested => {
Some(Message::CloseWindow(window))
}
window::Event::Opened { position, .. } => {
Some(Message::WindowOpened(window, position))
}
window::Event::Closed => {
Some(Message::WindowClosed(window))
}
_ => None,
}
} else {
None
}
})
window::closings().map(Message::WindowClosed)
}
}
@ -200,7 +189,7 @@ impl Window {
];
let new_window_button =
button(text("New Window")).on_press(Message::NewWindow);
button(text("New Window")).on_press(Message::OpenWindow);
let content = scrollable(
column![scale_input, title_input, new_window_button]

View file

@ -34,7 +34,7 @@ struct Example {
enum Message {
Crop,
Screenshot,
ScreenshotData(Screenshot),
Screenshotted(Screenshot),
Png,
PngSaved(Result<String, PngError>),
XInputChanged(Option<u32>),
@ -48,9 +48,9 @@ impl Example {
match message {
Message::Screenshot => {
return iced::window::screenshot(window::Id::MAIN)
.map(Message::ScreenshotData);
.map(Message::Screenshotted);
}
Message::ScreenshotData(screenshot) => {
Message::Screenshotted(screenshot) => {
self.screenshot = Some(screenshot);
}
Message::Png => {