More efficently resize at break point

Uses iced `events_with()` to only subscribe to window resize
events. The window width is stored in a static AtomicU32 so
that the subscription can compare to an old window width as to
only send messages when the width crosses the break point.

fix up
This commit is contained in:
13r0ck 2022-12-21 18:24:02 -07:00 committed by Jeremy Soller
parent bdf5f7da38
commit 8eff8a33fa

View file

@ -2,17 +2,17 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use cosmic::{ use cosmic::{
iced_native,
iced_native::window, iced_native::window,
iced::widget::{column, container, horizontal_space, row, text}, iced::widget::{column, container, horizontal_space, row, text},
iced::{self, Application, Command, Length}, iced::{self, Application, Command, Length, Subscription},
iced_lazy::responsive,
iced_winit::window::{close, drag, toggle_maximize, minimize}, iced_winit::window::{close, drag, toggle_maximize, minimize},
theme::{self, Theme}, theme::{self, Theme},
widget::{icon, list, nav_bar, nav_button, header_bar, settings, scrollable, spin_button::{SpinButtonModel, SpinMessage}}, widget::{icon, list, nav_bar, nav_button, header_bar, settings, scrollable, spin_button::{SpinButtonModel, SpinMessage}},
Element, Element,
ElementExt, ElementExt,
}; };
use std::vec; use std::{vec, sync::atomic::{AtomicU32, Ordering}};
mod bluetooth; mod bluetooth;
@ -115,6 +115,9 @@ impl Default for Page {
} }
} }
static WINDOW_WIDTH: AtomicU32 = AtomicU32::new(0);
const BREAK_POINT: u32 = 900;
#[derive(Default)] #[derive(Default)]
pub struct Window { pub struct Window {
title: String, title: String,
@ -168,7 +171,8 @@ pub enum Message {
Minimize, Minimize,
Maximize, Maximize,
InputChanged, InputChanged,
SpinButton(SpinMessage) SpinButton(SpinMessage),
WindowWidthChanged(u32),
} }
impl Window { impl Window {
@ -179,6 +183,10 @@ impl Window {
).into() ).into()
} }
fn is_condensed(&self) -> bool {
WINDOW_WIDTH.load(Ordering::Relaxed) < BREAK_POINT
}
fn parent_page_button(&self, sub_page: impl SubPage) -> Element<Message> { fn parent_page_button(&self, sub_page: impl SubPage) -> Element<Message> {
let page = sub_page.parent_page(); let page = sub_page.parent_page();
column!( column!(
@ -258,6 +266,22 @@ impl Application for Window {
self.title.clone() self.title.clone()
} }
fn subscription(&self) -> Subscription<Message> {
iced_native::subscription::events_with(|event, _| match event {
cosmic::iced::Event::Window(_window_id, window::Event::Resized{width, height}) => {
let old_width = WINDOW_WIDTH.load(Ordering::Relaxed);
if old_width == 0
|| old_width < BREAK_POINT && width > BREAK_POINT
|| old_width > BREAK_POINT && width < BREAK_POINT {
Some(width)
} else {
None
}
}
_ => None
}).map(Message::WindowWidthChanged)
}
fn update(&mut self, message: Message) -> iced::Command<Self::Message> { fn update(&mut self, message: Message) -> iced::Command<Self::Message> {
match message { match message {
Message::Page(page) => { Message::Page(page) => {
@ -282,6 +306,7 @@ impl Application for Window {
Message::RowSelected(row) => println!("Selected row {row}"), Message::RowSelected(row) => println!("Selected row {row}"),
Message::InputChanged => {}, Message::InputChanged => {},
Message::SpinButton(msg) => self.spin_button.update(msg), Message::SpinButton(msg) => self.spin_button.update(msg),
Message::WindowWidthChanged(new_width) => WINDOW_WIDTH.store(new_width, Ordering::Relaxed),
} }
@ -289,14 +314,7 @@ impl Application for Window {
} }
fn view(&self) -> Element<Message> { fn view(&self) -> Element<Message> {
// TODO: Adding responsive makes this regenerate on every size change, and regeneration let (sidebar_message, sidebar_toggled) = if self.is_condensed() {
// involves allocations for many different items. Ideally, we could only make the nav bar
// responsive and leave the content to be sized normally.
responsive(|size| {
//TODO: send a message when this happens instead of having everything be recalculated on resize
let condensed = size.width < 900.0;
let (sidebar_message, sidebar_toggled) = if condensed {
(Message::ToggleSidebarCondensed, self.sidebar_toggled_condensed) (Message::ToggleSidebarCondensed, self.sidebar_toggled_condensed)
} else { } else {
(Message::ToggleSidebar, self.sidebar_toggled) (Message::ToggleSidebar, self.sidebar_toggled)
@ -361,7 +379,7 @@ impl Application for Window {
.padding(8) .padding(8)
.style(theme::Container::Custom(nav_bar::nav_bar_sections_style)); .style(theme::Container::Custom(nav_bar::nav_bar_sections_style));
if ! condensed { if ! self.is_condensed() {
sidebar = sidebar.max_width(300) sidebar = sidebar.max_width(300)
} }
@ -369,7 +387,7 @@ impl Application for Window {
widgets.push(sidebar.debug(self.debug)); widgets.push(sidebar.debug(self.debug));
} }
if ! (condensed && sidebar_toggled) { if ! (self.is_condensed() && sidebar_toggled) {
let content: Element<_> = match self.page { let content: Element<_> = match self.page {
Page::Demo => self.view_demo(), Page::Demo => self.view_demo(),
Page::Networking(None) => settings::view_column(vec![ Page::Networking(None) => settings::view_column(vec![
@ -429,8 +447,6 @@ impl Application for Window {
.into(); .into();
column(vec![header, content]).into() column(vec![header, content]).into()
})
.into()
} }
fn theme(&self) -> Theme { fn theme(&self) -> Theme {