From 0953e5ab40f8dc5361c5e9d0ee9424387db4561f Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Sat, 7 Sep 2024 10:13:48 -0700 Subject: [PATCH] Window::icon --- CHANGELOG.md | 13 +++++++------ examples/window-properties.rs | 3 +++ src/window.rs | 30 ++++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbfc60c..401d87b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,19 +61,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Window::content_protected` - `Window::cursor_hittest` - - `Window::cursor_visible` - `Window::cursor_position` + - `Window::cursor_visible` - `Window::decorated` - - `Window::window_level` - - `Window::minimized` - - `Window::maximized` - - `Window::outer_size` + - `Window::icon` - `Window::inner_position` + - `Window::maximized` + - `Window::minimized` - `Window::outer_position` - - `Window::resized` + - `Window::outer_size` - `Window::resize_increments` + - `Window::resized` - `Window::transparent` - `Window::visible` + - `Window::window_level` - `run(&mut App)` is a new function that can provide a more concise way of executing applications that would normally require using `PendingApp`. - `PendingApp::on_startup` allows executing a function once the application's diff --git a/examples/window-properties.rs b/examples/window-properties.rs index bfdee3e..5d92d83 100644 --- a/examples/window-properties.rs +++ b/examples/window-properties.rs @@ -15,6 +15,8 @@ fn main() -> cushy::Result { let outer_size = Dynamic::new(Size::upx(0, 0)); let inner_position = Dynamic::new(Point::px(0, 0)); let outer_position = Dynamic::new(Point::px(0, 0)); + let icon = image::load_from_memory(include_bytes!("assets/ferris-happy.png")) + .expect("valid image"); let widgets = focused .map_each(|v| format!("focused: {:?}", v)) @@ -39,6 +41,7 @@ fn main() -> cushy::Result { .outer_position(outer_position) .maximized(maximized) .minimized(minimized) + .icon(Some(icon.into_rgba8())) .open(app) .expect("app running"); }) diff --git a/src/window.rs b/src/window.rs index e935dd3..72561c4 100644 --- a/src/window.rs +++ b/src/window.rs @@ -31,7 +31,7 @@ use kludgine::app::winit::event::{ use kludgine::app::winit::keyboard::{ Key, KeyLocation, NamedKey, NativeKeyCode, PhysicalKey, SmolStr, }; -use kludgine::app::winit::window::{self, Cursor, WindowLevel}; +use kludgine::app::winit::window::{self, Cursor, Icon, WindowLevel}; use kludgine::app::{winit, WindowBehavior as _}; use kludgine::cosmic_text::{fontdb, Family, FamilyOwned}; use kludgine::drawing::Drawing; @@ -548,6 +548,7 @@ where inner_position: Option>>, outer_position: Option>>, close_requested: Option>, + icon: Option>>, } impl Default for Window @@ -638,6 +639,7 @@ where outer_size: None, inner_position: None, outer_position: None, + icon: None, } } @@ -867,6 +869,12 @@ where self.title = title.into_value(); self } + + /// Sets the window's icon. + pub fn icon(mut self, icon: impl IntoValue>) -> Self { + self.icon = Some(icon.into_value()); + self + } } impl Run for Window @@ -932,6 +940,7 @@ where inner_position: self.inner_position.unwrap_or_default(), outer_position: self.outer_position.unwrap_or_default(), outer_size: self.outer_size.unwrap_or_default(), + window_icon: self.icon.unwrap_or_default(), }), pending: self.pending, }, @@ -1028,6 +1037,7 @@ struct OpenWindow { visible: Tracked>, outer_position: Tracked>>, inner_position: Dynamic>, + window_icon: Tracked>>, } impl OpenWindow @@ -1461,6 +1471,7 @@ where outer_size: settings.outer_size, inner_position: settings.inner_position, outer_position: Tracked::from(settings.outer_position), + window_icon: Tracked::from(settings.window_icon), } } @@ -1646,6 +1657,7 @@ where { self.update_ized(window); if let Some(winit) = window.winit() { + let mut redraw = false; let handle = window.handle(self.redraw_status.clone()); self.outer_position.inner_sync_when_changed(handle.clone()); if let Some(position) = self.outer_position.updated() { @@ -1693,6 +1705,18 @@ where self.resizable.inner_sync_when_changed(handle.clone()); if let Some(resizable) = self.resizable.updated() { winit.set_resizable(*resizable); + redraw = true; + } + self.window_icon.inner_sync_when_changed(handle.clone()); + if let Some(icon) = self.window_icon.updated() { + let icon = icon.as_ref().map(|icon| { + Icon::from_rgba(icon.as_raw().clone(), icon.width(), icon.height()) + .expect("valid image") + }); + winit.set_window_icon(icon); + } + + if redraw { window.set_needs_redraw(); } } @@ -2472,7 +2496,7 @@ pub(crate) mod sealed { use figures::units::{Px, UPx}; use figures::{Fraction, Point, Size}; - use image::DynamicImage; + use image::{DynamicImage, RgbaImage}; use kludgine::app::winit::window::{UserAttentionType, WindowLevel}; use kludgine::Color; use parking_lot::Mutex; @@ -2529,6 +2553,7 @@ pub(crate) mod sealed { pub inner_position: Dynamic>, pub outer_position: Dynamic>, pub outer_size: Dynamic>, + pub window_icon: Value>, } #[derive(Debug, Clone)] @@ -3139,6 +3164,7 @@ impl StandaloneWindowBuilder { inner_position: Dynamic::default(), outer_position: Dynamic::default(), outer_size: Dynamic::default(), + window_icon: Value::Constant(None), }, );