diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index af5b059b..3e3a042e 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -17,13 +17,13 @@ jobs: - name: Install Rust nightly uses: dtolnay/rust-toolchain@master with: - toolchain: nightly-2026-04-27 + toolchain: nightly-2025-07-31 - name: System dependencies run: sudo apt-get update; sudo apt-get install -y libxkbcommon-dev libwayland-dev - name: Build documentation run: | RUSTDOCFLAGS="--cfg docsrs" \ - cargo +nightly-2026-04-27 doc --no-deps \ + cargo +nightly-2025-07-31 doc --no-deps \ -p cosmic-client-toolkit \ -p cosmic-protocols \ -p libcosmic \ diff --git a/.zed/settings.json b/.zed/settings.json deleted file mode 100644 index 2cc7b98d..00000000 --- a/.zed/settings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "format_on_save": "on", - "lsp": { - "rust-analyzer": { - "initialization_options": { - "check": { - "command": "clippy", - }, - "rustfmt": { - "extraArgs": ["+nightly"], - }, - }, - }, - }, -} diff --git a/Cargo.toml b/Cargo.toml index d220eed3..64172899 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ name = "libcosmic-yoda" version = "0.1.0-yoda.2" edition = "2024" -rust-version = "1.93" +rust-version = "1.90" [lib] name = "cosmic" @@ -128,9 +128,9 @@ async-std = [ apply = "0.3.0" ashpd = { version = "0.12.3", default-features = false, optional = true } async-fs = { version = "2.2", optional = true } -async-std = { workspace = true, optional = true } +async-std = { version = "1.13", optional = true } auto_enums = "0.8.8" -cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "c253ec1", optional = true } +cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "160b086", optional = true } jiff = "0.2" cosmic-config = { path = "cosmic-config" } cosmic-settings-config = { git = "https://github.com/pop-os/cosmic-settings-daemon", optional = true } @@ -153,26 +153,25 @@ image-extras = { version = "0.1.0", default-features = false, features = [ "xpm", "xbm", ], optional = true } -libc = { version = "0.2.186", optional = true } +libc = { version = "0.2.183", optional = true } log = "0.4" mime = { version = "0.3.17", optional = true } -palette.workspace = true +palette = "0.7.6" rfd = { version = "0.16.0", default-features = false, features = [ "xdg-portal", ], optional = true } rustix = { version = "1.1", features = ["pipe", "process"], optional = true } -serde = { workspace = true, features = ["derive"] } +serde = { version = "1.0.228", features = ["derive"] } slotmap = "1.1.1" smol = { version = "2.0.2", optional = true } -thiserror.workspace = true +thiserror = "2.0.18" taffy = { version = "0.9.2", features = ["grid"] } -tokio = { workspace = true, optional = true } -tracing.workspace = true -unicode-segmentation = "1.13" +tokio = { version = "1.50.0", optional = true } +tracing = "0.1.44" +unicode-segmentation = "1.12" url = "2.5.8" -zbus = { workspace = true, optional = true } +zbus = { version = "5.14.0", default-features = false, optional = true } float-cmp = "0.10.0" -ron = { workspace = true, optional = true } # Enable DBus feature on Linux targets [target.'cfg(target_os = "linux")'.dependencies] @@ -248,6 +247,10 @@ git = "https://github.com/pop-os/cosmic-panel" # path = "../cosmic-panel/cosmic-panel-config" optional = true +[dependencies.ron] +version = "0.12" +optional = true + [workspace] members = [ "cosmic-config", @@ -259,15 +262,7 @@ members = [ exclude = ["iced", "examples"] [workspace.dependencies] -async-std = "1.13" -dirs = "6.0" -palette = "0.7" -ron = "0.12" -serde = "1.0" -thiserror = "2.0" -tracing = "0.1" -tokio = "1.52" -zbus = {version = "5.15", default-features = false} +dirs = "6.0.0" # Speed up snapshot diffing in cosmic-theme tests. Cargo silently ignores # [profile.*] blocks in non-root manifests, so this lives at the diff --git a/README.md b/README.md index 698316db..23da97bc 100644 --- a/README.md +++ b/README.md @@ -20,24 +20,6 @@ While libcosmic is written entirely in Rust, some of its dependencies may requir sudo apt install cargo cmake just libexpat1-dev libfontconfig-dev libfreetype-dev libxkbcommon-dev pkgconf ``` -## Made-for-COSMIC Flatpak IDs - -To identify a project as a COSMIC Application, add `com.system76.CosmicApplication` to the provides section of the project's metainfo. - -```xml - - com.system76.CosmicApplication - -``` - -For COSMIC Applets, use `com.system76.CosmicApplet`. - -```xml - - com.system76.CosmicApplet - -``` - ## Examples Some examples are included in the [examples](./examples) directory to to kickstart your diff --git a/cosmic-config/Cargo.toml b/cosmic-config/Cargo.toml index a81d13fd..2a626f6b 100644 --- a/cosmic-config/Cargo.toml +++ b/cosmic-config/Cargo.toml @@ -15,16 +15,16 @@ zbus = { version = "5.14.0", default-features = false, optional = true } atomicwrites = { git = "https://github.com/jackpot51/rust-atomicwrites" } calloop = { version = "0.14.4", optional = true } notify = "8.2.0" -ron.workspace = true -serde.workspace = true +ron = "0.12.0" +serde = "1.0.228" cosmic-config-derive = { path = "../cosmic-config-derive/", optional = true } iced = { path = "../iced/", default-features = false, optional = true } iced_futures = { path = "../iced/futures/", default-features = false, optional = true } futures-util = { version = "0.3", optional = true } dirs.workspace = true -tokio = { workspace = true, optional = true, features = ["time"] } -async-std = { workspace = true, optional = true } -tracing.workspace = true +tokio = { version = "1.50", optional = true, features = ["time"] } +async-std = { version = "1.13", optional = true } +tracing = "0.1" [target.'cfg(unix)'.dependencies] xdg = "3.0" diff --git a/cosmic-config/src/dbus.rs b/cosmic-config/src/dbus.rs index 9b6e8697..da7bcb68 100644 --- a/cosmic-config/src/dbus.rs +++ b/cosmic-config/src/dbus.rs @@ -1,12 +1,13 @@ -use std::any::TypeId; -use std::ops::Deref; +use std::{any::TypeId, ops::Deref}; use crate::{CosmicConfigEntry, Update}; use cosmic_settings_daemon::{Changed, ConfigProxy, CosmicSettingsDaemonProxy}; use futures_util::SinkExt; -use iced_futures::futures::future::pending; -use iced_futures::futures::{self, StreamExt}; -use iced_futures::{Subscription, stream}; +use iced_futures::{ + Subscription, + futures::{self, StreamExt, future::pending}, + stream, +}; pub async fn settings_daemon_proxy() -> zbus::Result> { let conn = zbus::Connection::session().await?; diff --git a/cosmic-config/src/lib.rs b/cosmic-config/src/lib.rs index 2af498ff..c8eda064 100644 --- a/cosmic-config/src/lib.rs +++ b/cosmic-config/src/lib.rs @@ -1,13 +1,16 @@ //! Integrations for cosmic-config — the cosmic configuration system. -use notify::event::{EventKind, ModifyKind, RenameMode}; -use notify::{RecommendedWatcher, Watcher}; -use serde::Serialize; -use serde::de::DeserializeOwned; -use std::io::Write; -use std::path::{Path, PathBuf}; -use std::sync::Mutex; -use std::{env, fmt, fs}; +use notify::{ + RecommendedWatcher, Watcher, + event::{EventKind, ModifyKind, RenameMode}, +}; +use serde::{Serialize, de::DeserializeOwned}; +use std::{ + env, fmt, fs, + io::Write, + path::{Path, PathBuf}, + sync::Mutex, +}; /// Get the config directory, with Flatpak sandbox support. /// In Flatpak, HOST_XDG_CONFIG_HOME points to the real user config directory, @@ -51,22 +54,6 @@ fn get_state_dir() -> Option { dirs::state_dir() } -/// Get the data directory, with Flatpak sandbox support. -fn get_data_dir() -> Option { - // Check if we're running in Flatpak - if env::var_os("FLATPAK_ID").is_some() { - // Try HOST_XDG_DATA_HOME first - if let Some(host_data) = env::var_os("HOST_XDG_DATA_HOME") { - return Some(PathBuf::from(host_data)); - } - // Fallback: try to construct from HOME - if let Some(home) = env::var_os("HOME") { - return Some(PathBuf::from(home).join(".local").join("share")); - } - } - dirs::data_dir() -} - #[cfg(feature = "subscription")] mod subscription; #[cfg(feature = "subscription")] @@ -279,24 +266,6 @@ impl Config { }) } - /// Get data for the given application name and config version. - pub fn new_data(name: &str, version: u64) -> Result { - // Look for [name]/v[version] - let path = sanitize_name(name)?.join(format!("v{}", version)); - - // Get libcosmic user data directory - let mut user_path = get_data_dir().ok_or(Error::NoConfigDirectory)?; - user_path.push("cosmic"); - user_path.push(path); - // Create new data directory if not found. - fs::create_dir_all(&user_path)?; - - Ok(Self { - system_path: None, - user_path: Some(user_path), - }) - } - // Start a transaction (to set multiple configs at the same time) #[inline] pub fn transaction(&self) -> ConfigTransaction<'_> { diff --git a/cosmic-config/src/subscription.rs b/cosmic-config/src/subscription.rs index f0387877..8246a12d 100644 --- a/cosmic-config/src/subscription.rs +++ b/cosmic-config/src/subscription.rs @@ -1,9 +1,7 @@ -use iced_futures::futures::channel::mpsc; -use iced_futures::futures::{SinkExt, Stream}; -use iced_futures::stream; +use iced_futures::futures::SinkExt; +use iced_futures::{futures::channel::mpsc, stream}; use notify::RecommendedWatcher; -use std::borrow::Cow; -use std::hash::Hash; +use std::{borrow::Cow, hash::Hash}; use crate::{Config, CosmicConfigEntry}; @@ -79,8 +77,7 @@ async fn start_listening, output: &mut mpsc::Sender>, ) -> ConfigState { - use iced_futures::futures::StreamExt; - use iced_futures::futures::future::pending; + use iced_futures::futures::{StreamExt, future::pending}; match state { ConfigState::Init(config_id, version, is_state) => { diff --git a/cosmic-theme/Cargo.toml b/cosmic-theme/Cargo.toml index b5bffa17..9ee641e8 100644 --- a/cosmic-theme/Cargo.toml +++ b/cosmic-theme/Cargo.toml @@ -15,13 +15,13 @@ export = ["serde_json"] no-default = [] [dependencies] -palette = { workspace = true, features = ["serializing"] } +palette = { version = "0.7.6", features = ["serializing"] } almost = "0.2" -serde = { workspace = true, features = ["derive"] } +serde = { version = "1.0.228", features = ["derive"] } serde_json = { version = "1.0.149", optional = true, features = [ "preserve_order", ] } -ron.workspace = true +ron = "0.12.0" csscolorparser = { version = "0.8.3", features = ["serde"] } cosmic-config = { path = "../cosmic-config/", default-features = false, features = [ "subscription", @@ -29,7 +29,7 @@ cosmic-config = { path = "../cosmic-config/", default-features = false, features ] } configparser = "3.1.0" dirs.workspace = true -thiserror.workspace = true +thiserror = "2.0.18" [dev-dependencies] insta = "1.47.2" diff --git a/cosmic-theme/src/model/corner.rs b/cosmic-theme/src/model/corner.rs index f2fa95ec..ecd18c0b 100644 --- a/cosmic-theme/src/model/corner.rs +++ b/cosmic-theme/src/model/corner.rs @@ -29,51 +29,3 @@ impl Default for CornerRadii { } } } - -/// Roundness options for the Cosmic theme -#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub enum Roundness { - /// Round style - #[default] - Round, - /// Slightly round style - SlightlyRound, - /// Square style - Square, -} - -impl From for CornerRadii { - fn from(value: Roundness) -> Self { - match value { - Roundness::Round => CornerRadii::default(), - Roundness::SlightlyRound => CornerRadii { - radius_0: [0.0; 4], - radius_xs: [2.0; 4], - radius_s: [8.0; 4], - radius_m: [8.0; 4], - radius_l: [8.0; 4], - radius_xl: [8.0; 4], - }, - Roundness::Square => CornerRadii { - radius_0: [0.0; 4], - radius_xs: [2.0; 4], - radius_s: [2.0; 4], - radius_m: [2.0; 4], - radius_l: [2.0; 4], - radius_xl: [2.0; 4], - }, - } - } -} - -impl From for Roundness { - fn from(value: CornerRadii) -> Self { - if (value.radius_m[0] - 16.0).abs() < 0.01 { - Self::Round - } else if (value.radius_m[0] - 8.0).abs() < 0.01 { - Self::SlightlyRound - } else { - Self::Square - } - } -} diff --git a/cosmic-theme/src/model/density.rs b/cosmic-theme/src/model/density.rs new file mode 100644 index 00000000..7655361c --- /dev/null +++ b/cosmic-theme/src/model/density.rs @@ -0,0 +1,69 @@ +use crate::Spacing; +use serde::{Deserialize, Serialize}; + +/// Density options for the Cosmic theme +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] +pub enum Density { + /// Lower padding/spacing of elements + Compact, + /// Higher padding/spacing of elements + Spacious, + /// Standard padding/spacing of elements + #[default] + Standard, +} + +impl From for Spacing { + fn from(value: Density) -> Self { + match value { + Density::Compact => Spacing { + space_none: 0, + space_xxxs: 4, + space_xxs: 4, + space_xs: 8, + space_s: 8, + space_m: 16, + space_l: 24, + space_xl: 32, + space_xxl: 48, + space_xxxl: 64, + }, + Density::Spacious => Spacing { + space_none: 4, + space_xxxs: 8, + space_xxs: 12, + space_xs: 16, + space_s: 24, + space_m: 32, + space_l: 48, + space_xl: 64, + space_xxl: 128, + space_xxxl: 160, + }, + Density::Standard => Spacing { + space_none: 0, + space_xxxs: 4, + space_xxs: 8, + space_xs: 12, + space_s: 16, + space_m: 24, + space_l: 32, + space_xl: 48, + space_xxl: 64, + space_xxxl: 128, + }, + } + } +} + +impl From for Density { + fn from(value: Spacing) -> Self { + if value.space_m.saturating_sub(16) == 0 { + Self::Compact + } else if value.space_m.saturating_sub(24) == 0 { + Self::Standard + } else { + Self::Spacious + } + } +} diff --git a/cosmic-theme/src/model/mod.rs b/cosmic-theme/src/model/mod.rs index 19370dee..f48d1a8d 100644 --- a/cosmic-theme/src/model/mod.rs +++ b/cosmic-theme/src/model/mod.rs @@ -1,5 +1,6 @@ pub use corner::*; pub use cosmic_palette::*; +pub use density::*; pub use derivation::*; pub use mode::*; pub use spacing::*; @@ -7,6 +8,7 @@ pub use theme::*; mod corner; mod cosmic_palette; +mod density; mod derivation; mod mode; mod spacing; diff --git a/cosmic-theme/src/model/spacing.rs b/cosmic-theme/src/model/spacing.rs index f02cf510..93b1bf43 100644 --- a/cosmic-theme/src/model/spacing.rs +++ b/cosmic-theme/src/model/spacing.rs @@ -41,59 +41,3 @@ impl Default for Spacing { } } } - -/// Density options for the Cosmic theme -#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub enum Density { - /// Lower padding/spacing of elements - Compact, - /// Standard padding/spacing of elements - #[default] - Standard, - /// Higher padding/spacing of elements - Spacious, -} - -impl From for Spacing { - fn from(value: Density) -> Self { - match value { - Density::Compact => Spacing { - space_none: 0, - space_xxxs: 4, - space_xxs: 4, - space_xs: 8, - space_s: 8, - space_m: 16, - space_l: 24, - space_xl: 32, - space_xxl: 48, - space_xxxl: 64, - }, - Density::Standard => Spacing::default(), - Density::Spacious => Spacing { - space_none: 4, - space_xxxs: 8, - space_xxs: 12, - space_xs: 16, - space_s: 24, - space_m: 32, - space_l: 48, - space_xl: 64, - space_xxl: 128, - space_xxxl: 160, - }, - } - } -} - -impl From for Density { - fn from(value: Spacing) -> Self { - if value.space_m.saturating_sub(16) == 0 { - Self::Compact - } else if value.space_m.saturating_sub(24) == 0 { - Self::Standard - } else { - Self::Spacious - } - } -} diff --git a/cosmic-theme/src/model/theme.rs b/cosmic-theme/src/model/theme.rs index 0c06005e..36480f9f 100644 --- a/cosmic-theme/src/model/theme.rs +++ b/cosmic-theme/src/model/theme.rs @@ -1,13 +1,13 @@ -use crate::composite::over; -use crate::steps::{color_index, get_small_widget_color, get_surface_color, get_text, steps}; use crate::{ Component, Container, CornerRadii, CosmicPalette, CosmicPaletteInner, DARK_PALETTE, LIGHT_PALETTE, NAME, Spacing, ThemeMode, + composite::over, + steps::{color_index, get_small_widget_color, get_surface_color, get_text, steps}, }; use cosmic_config::{Config, CosmicConfigEntry}; -use palette::color_difference::Wcag21RelativeContrast; -use palette::rgb::Rgb; -use palette::{IntoColor, Oklcha, Srgb, Srgba, WithAlpha}; +use palette::{ + IntoColor, Oklcha, Srgb, Srgba, WithAlpha, color_difference::Wcag21RelativeContrast, rgb::Rgb, +}; use serde::{Deserialize, Serialize}; use std::num::NonZeroUsize; @@ -75,8 +75,6 @@ pub struct Theme { pub icon_button: Component, /// link button element colors pub link_button: Component, - /// list button element colors - pub list_button: Component, /// text button element colors pub text_button: Component, /// button component styling @@ -1293,15 +1291,6 @@ impl ThemeBuilder { component.on_disabled = over(component.on.with_alpha(0.5), component.base); component }, - list_button: Component::component( - Srgba::new(0.0, 0.0, 0.0, 0.0), - accent, - on_bg_component, - Srgba::new(0.0, 0.0, 0.0, 0.0), - button_pressed_overlay, - is_high_contrast, - control_steps_array[8], - ), success: Component::colored_component( success, control_steps_array[0], diff --git a/cosmic-theme/src/output/mod.rs b/cosmic-theme/src/output/mod.rs index 04dce39f..19f7bc5b 100644 --- a/cosmic-theme/src/output/mod.rs +++ b/cosmic-theme/src/output/mod.rs @@ -1,6 +1,5 @@ use configparser::ini::WriteOptions; -use palette::Srgba; -use palette::rgb::Rgba; +use palette::{Srgba, rgb::Rgba}; use thiserror::Error; use crate::Theme; diff --git a/cosmic-theme/src/output/qt56ct_output.rs b/cosmic-theme/src/output/qt56ct_output.rs index 16df211f..43a45470 100644 --- a/cosmic-theme/src/output/qt56ct_output.rs +++ b/cosmic-theme/src/output/qt56ct_output.rs @@ -1,12 +1,12 @@ use crate::Theme; use configparser::ini::Ini; -use palette::blend::Compose; -use palette::rgb::Rgba; -use palette::{Mix, Srgba, WithAlpha}; -use std::fs::{self, File}; -use std::io::Write; -use std::path::PathBuf; -use std::vec; +use palette::{Mix, Srgba, WithAlpha, blend::Compose, rgb::Rgba}; +use std::{ + fs::{self, File}, + io::Write, + path::PathBuf, + vec, +}; use super::{OutputError, qt_settings_ini_style}; diff --git a/cosmic-theme/src/output/qt_output.rs b/cosmic-theme/src/output/qt_output.rs index 84614e7b..d42d553b 100644 --- a/cosmic-theme/src/output/qt_output.rs +++ b/cosmic-theme/src/output/qt_output.rs @@ -1,11 +1,12 @@ use crate::Theme; use configparser::ini::Ini; use cosmic_config::CosmicConfigEntry; -use palette::blend::Compose; -use palette::{Mix, Srgba}; -use std::fs::{self, File}; -use std::io::{self, Write}; -use std::path::{Path, PathBuf}; +use palette::{Mix, Srgba, blend::Compose}; +use std::{ + fs::{self, File}, + io::{self, Write}, + path::{Path, PathBuf}, +}; use super::{OutputError, qt_settings_ini_style}; diff --git a/cosmic-theme/src/steps.rs b/cosmic-theme/src/steps.rs index d156722c..6ebf1015 100644 --- a/cosmic-theme/src/steps.rs +++ b/cosmic-theme/src/steps.rs @@ -1,8 +1,7 @@ use std::num::NonZeroUsize; use almost::equal; -use palette::convert::FromColorUnclamped; -use palette::{ClampAssign, FromColor, Lch, Oklcha, Srgb, Srgba}; +use palette::{ClampAssign, FromColor, Lch, Oklcha, Srgb, Srgba, convert::FromColorUnclamped}; /// Get an array of 100 colors with a specific hue and chroma /// over the full range of lightness. diff --git a/examples/about/src/main.rs b/examples/about/src/main.rs index d1ea475e..c25a9b9a 100644 --- a/examples/about/src/main.rs +++ b/examples/about/src/main.rs @@ -8,8 +8,7 @@ use cosmic::app::{Core, Settings, Task}; use cosmic::executor; use cosmic::iced::{alignment, Length, Size}; use cosmic::prelude::*; -use cosmic::widget::about::About; -use cosmic::widget::{self, nav_bar}; +use cosmic::widget::{self, about::About, nav_bar}; /// Runs application with these settings #[rustfmt::skip] diff --git a/examples/applet/src/window.rs b/examples/applet/src/window.rs index 57546ab1..22903eac 100644 --- a/examples/applet/src/window.rs +++ b/examples/applet/src/window.rs @@ -4,8 +4,7 @@ use cosmic::iced::core::window; use cosmic::iced::window::Id; use cosmic::iced::{Length, Rectangle}; use cosmic::surface::action::{app_popup, destroy_popup}; -use cosmic::widget::dropdown::popup_dropdown; -use cosmic::widget::{list_column, settings, toggler}; +use cosmic::widget::{dropdown::popup_dropdown, list_column, settings, toggler}; use cosmic::Element; const ID: &str = "com.system76.CosmicAppletExample"; diff --git a/examples/application/src/main.rs b/examples/application/src/main.rs index 05841f5b..f6e571e0 100644 --- a/examples/application/src/main.rs +++ b/examples/application/src/main.rs @@ -5,10 +5,9 @@ use cosmic::app::Settings; use cosmic::iced::{Alignment, Length, Size}; -use cosmic::prelude::*; use cosmic::widget::menu::{self, KeyBind}; use cosmic::widget::nav_bar; -use cosmic::{executor, iced, widget, Core}; +use cosmic::{executor, iced, prelude::*, widget, Core}; use std::collections::HashMap; use std::sync::LazyLock; @@ -240,9 +239,7 @@ impl cosmic::Application for App { widget::progress_bar::linear::Linear::new() .girth(10.0) .progress(self.progress) - .width(Length::Fill) - .markers([0.25, 0.5, 0.75]) - .segment_spacing(2), + .width(Length::Fill), ) .push( widget::progress_bar::circular::Circular::new() diff --git a/examples/config/src/main.rs b/examples/config/src/main.rs index dfcc5b99..f6fb5c0d 100644 --- a/examples/config/src/main.rs +++ b/examples/config/src/main.rs @@ -88,7 +88,4 @@ pub fn main() { println!("Testing state"); test_config(Config::new_state("com.system76.Example", 1).unwrap()); - - println!("Testing data"); - test_config(Config::new_data("com.system76.Example", 1).unwrap()); } diff --git a/examples/cosmic/src/window.rs b/examples/cosmic/src/window.rs index 4168718d..9fce8767 100644 --- a/examples/cosmic/src/window.rs +++ b/examples/cosmic/src/window.rs @@ -23,11 +23,15 @@ use cosmic::{ Element, }; use cosmic_time::{Instant, Timeline}; -use std::cell::RefCell; -use std::rc::Rc; -use std::sync::atomic::{AtomicU32, Ordering}; -use std::sync::Arc; -use std::vec; +use std::{ + cell::RefCell, + rc::Rc, + sync::{ + atomic::{AtomicU32, Ordering}, + Arc, + }, + vec, +}; // XXX The use of button is removed because it assigns the same ID to multiple buttons, causing a crash when a11y is enabled... // static BTN: Lazy = Lazy::new(|| id::Id::new("BTN")); diff --git a/examples/cosmic/src/window/bluetooth.rs b/examples/cosmic/src/window/bluetooth.rs index 2878b46a..1b5892f6 100644 --- a/examples/cosmic/src/window/bluetooth.rs +++ b/examples/cosmic/src/window/bluetooth.rs @@ -1,7 +1,9 @@ use super::{Page, Window}; -use cosmic::iced::widget::{column, text}; -use cosmic::widget::{list_column, settings, toggler}; -use cosmic::Element; +use cosmic::{ + iced::widget::{column, text}, + widget::{list_column, settings, toggler}, + Element, +}; #[derive(Clone, Copy, Debug)] pub enum Message { diff --git a/examples/cosmic/src/window/demo.rs b/examples/cosmic/src/window/demo.rs index 20a730b5..0d31fa93 100644 --- a/examples/cosmic/src/window/demo.rs +++ b/examples/cosmic/src/window/demo.rs @@ -1,17 +1,19 @@ -use std::cell::RefCell; -use std::rc::Rc; +use std::{cell::RefCell, rc::Rc}; use apply::Apply; -use cosmic::iced::widget::{checkbox, column, progress_bar, radio, slider, text}; -use cosmic::iced::{Alignment, Length}; -use cosmic::iced_core::id; -use cosmic::theme::ThemeType; -use cosmic::widget::color_picker::ColorPickerUpdate; -use cosmic::widget::{ - button, dropdown, icon, layer_container as container, segmented_button, segmented_control, - settings, spin_button, tab_bar, toggler, ColorPickerModel, +use cosmic::{ + cosmic_theme, + iced::widget::{checkbox, column, progress_bar, radio, slider, text}, + iced::{Alignment, Length}, + iced_core::id, + theme::ThemeType, + widget::{ + button, color_picker::ColorPickerUpdate, dropdown, icon, layer_container as container, + segmented_button, segmented_control, settings, spin_button, tab_bar, toggler, + ColorPickerModel, + }, + Element, }; -use cosmic::{cosmic_theme, Element}; use cosmic_time::{anim, chain, Timeline}; use fraction::{Decimal, ToPrimitive}; use once_cell::sync::Lazy; diff --git a/examples/cosmic/src/window/desktop.rs b/examples/cosmic/src/window/desktop.rs index a087de9e..46a4e5b8 100644 --- a/examples/cosmic/src/window/desktop.rs +++ b/examples/cosmic/src/window/desktop.rs @@ -1,7 +1,10 @@ -use cosmic::iced::widget::{column, container, horizontal_space, image, row, svg, text}; -use cosmic::iced::Length; -use cosmic::widget::{list_column, settings, toggler}; -use cosmic::{theme, Element}; +use cosmic::{ + iced::widget::{column, container, horizontal_space, image, row, svg, text}, + iced::Length, + theme, + widget::{list_column, settings, toggler}, + Element, +}; use super::{Page, SubPage, Window}; diff --git a/examples/cosmic/src/window/system_and_accounts.rs b/examples/cosmic/src/window/system_and_accounts.rs index 5f498857..ed1bd004 100644 --- a/examples/cosmic/src/window/system_and_accounts.rs +++ b/examples/cosmic/src/window/system_and_accounts.rs @@ -1,7 +1,9 @@ -use cosmic::iced::widget::{horizontal_space, row, text}; -use cosmic::iced::Length; -use cosmic::widget::{icon, list_column, settings}; -use cosmic::Element; +use cosmic::{ + iced::widget::{horizontal_space, row, text}, + iced::Length, + widget::{icon, list_column, settings}, + Element, +}; use super::{Message, Page, SubPage, Window}; diff --git a/examples/menu/src/main.rs b/examples/menu/src/main.rs index 900d0322..da0c3231 100644 --- a/examples/menu/src/main.rs +++ b/examples/menu/src/main.rs @@ -9,9 +9,11 @@ use std::{env, process}; use cosmic::app::{Core, Settings, Task}; use cosmic::iced::alignment::{Horizontal, Vertical}; use cosmic::iced::keyboard::Key; -use cosmic::iced::{window, Length, Size}; +use cosmic::iced::window; +use cosmic::iced::{Length, Size}; use cosmic::widget::menu::action::MenuAction; -use cosmic::widget::menu::key_bind::{KeyBind, Modifier}; +use cosmic::widget::menu::key_bind::KeyBind; +use cosmic::widget::menu::key_bind::Modifier; use cosmic::widget::menu::{self, ItemHeight, ItemWidth}; use cosmic::widget::RcElementWrapper; use cosmic::{executor, Element}; diff --git a/examples/multi-window/src/window.rs b/examples/multi-window/src/window.rs index a6d40d36..754a0d86 100644 --- a/examples/multi-window/src/window.rs +++ b/examples/multi-window/src/window.rs @@ -1,11 +1,13 @@ use std::collections::HashMap; -use cosmic::app::Core; -use cosmic::iced::core::{id, Alignment, Length, Point}; -use cosmic::iced::widget::{column, container, scrollable, text}; -use cosmic::iced::{self, event, window, Subscription}; -use cosmic::prelude::*; -use cosmic::widget::{button, header_bar}; +use cosmic::{ + app::Core, + iced::core::{id, Alignment, Length, Point}, + iced::widget::{column, container, scrollable, text}, + iced::{self, event, window, Subscription}, + prelude::*, + widget::{button, header_bar}, +}; #[derive(Debug, Clone, PartialEq)] pub enum Message { diff --git a/examples/spin-button/src/main.rs b/examples/spin-button/src/main.rs index 0228291c..47db4dce 100644 --- a/examples/spin-button/src/main.rs +++ b/examples/spin-button/src/main.rs @@ -1,8 +1,15 @@ -use cosmic::app::{Core, Task}; -use cosmic::iced::alignment::{Horizontal, Vertical}; -use cosmic::iced::{self, Alignment, Length, Size}; +use cosmic::iced::Length; use cosmic::widget::{column, container, spin_button}; -use cosmic::{Application, Apply, Element}; +use cosmic::Apply; +use cosmic::{ + app::{Core, Task}, + iced::{ + self, + alignment::{Horizontal, Vertical}, + Alignment, Size, + }, + Application, Element, +}; use fraction::Decimal; pub struct SpinButtonExamplApp { diff --git a/examples/subscriptions/src/main.rs b/examples/subscriptions/src/main.rs index 325af162..17e630aa 100644 --- a/examples/subscriptions/src/main.rs +++ b/examples/subscriptions/src/main.rs @@ -5,8 +5,7 @@ use cosmic::app::{Core, Settings, Task}; use cosmic::iced::Subscription; -use cosmic::prelude::*; -use cosmic::{executor, widget}; +use cosmic::{executor, prelude::*, widget}; /// Runs application with these settings fn main() -> Result<(), Box> { diff --git a/examples/table-view/src/main.rs b/examples/table-view/src/main.rs index e518b3cc..d2478429 100644 --- a/examples/table-view/src/main.rs +++ b/examples/table-view/src/main.rs @@ -9,7 +9,8 @@ use chrono::Datelike; use cosmic::app::{Core, Settings, Task}; use cosmic::iced::Size; use cosmic::prelude::*; -use cosmic::widget::{self, nav_bar, table}; +use cosmic::widget::table; +use cosmic::widget::{self, nav_bar}; use cosmic::{executor, iced}; #[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)] diff --git a/i18n/el/libcosmic_yoda.ftl b/i18n/el/libcosmic_yoda.ftl index f4fe0b31..e69de29b 100644 --- a/i18n/el/libcosmic_yoda.ftl +++ b/i18n/el/libcosmic_yoda.ftl @@ -1,34 +0,0 @@ -close = Κλείσιμο -february = Φεβρουάριος { $year } -documenters = Τεκμηριωτές -november = Νοέμβριος { $year } -may = Μάιος { $year } -april = Απρίλιος { $year } -translators = Μεταφραστές -artists = Καλλιτέχνες -license = Άδεια χρήσης -december = Δεκέμβριος { $year } -links = Σύνδεσμοι -march = Μάρτιος { $year } -june = Ιούνιος { $year } -august = Αύγουστος { $year } -developers = Προγραμματιστές -july = Ιούλιος { $year } -september = Σεπτέμβριος { $year } -designers = Σχεδιαστές -october = Οκτώβριος { $year } -january = Ιανουάριος { $year } -monday = Δευτέρα -mon = Δευ -tuesday = Τρίτη -tue = Τρί -wednesday = Τετάρτη -wed = Τετ -thursday = Πέμπτη -thu = Πέμ -friday = Παρασκευή -fri = Παρ -saturday = Σάββατο -sat = Σάβ -sunday = Κυριακή -sun = Κυρ diff --git a/i18n/lo/libcosmic.ftl b/i18n/lo/libcosmic.ftl deleted file mode 100644 index e69de29b..00000000 diff --git a/i18n/sr/libcosmic_yoda.ftl b/i18n/sr/libcosmic_yoda.ftl index e8b88303..e69de29b 100644 --- a/i18n/sr/libcosmic_yoda.ftl +++ b/i18n/sr/libcosmic_yoda.ftl @@ -1,34 +0,0 @@ -close = Затвори -february = Фебруар { $year } -documenters = Документатори -november = Новембар { $year } -may = Мај { $year } -april = Април { $year } -translators = Преводиоци -artists = Уметници -license = Дозвола -december = Децембар { $year } -links = Везе -march = Март { $year } -june = Јун { $year } -august = Август { $year } -developers = Програмери -july = Јул { $year } -september = Септембар { $year } -designers = Дизајнери -october = Октобар { $year } -january = Јануар { $year } -monday = Понедељак -mon = Пон -tuesday = Уторак -tue = Уто -wednesday = Среда -wed = Сре -thursday = Четвртак -thu = Чет -friday = Петак -fri = Пет -saturday = Субота -sat = Суб -sunday = Недеља -sun = Нед diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index c1578aaf..00000000 --- a/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -imports_granularity = "Module" diff --git a/src/app/action.rs b/src/app/action.rs index 166df16b..fb982acb 100644 --- a/src/app/action.rs +++ b/src/app/action.rs @@ -1,10 +1,10 @@ // Copyright 2023 System76 // SPDX-License-Identifier: MPL-2.0 -use crate::config::CosmicTk; +use crate::surface; use crate::theme::Theme; use crate::widget::nav_bar; -use crate::{keyboard_nav, surface}; +use crate::{config::CosmicTk, keyboard_nav}; #[cfg(all(feature = "wayland", target_os = "linux"))] use cctk::sctk::reexports::csd_frame::{WindowManagerCapabilities, WindowState}; use cosmic_theme::ThemeMode; diff --git a/src/app/mod.rs b/src/app/mod.rs index b2d82dcd..f53ee519 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -22,11 +22,11 @@ use crate::prelude::*; use crate::theme::THEME; use crate::widget::{container, id_container, menu, nav_bar, popover, space}; use apply::Apply; -use iced::{Length, Subscription, theme, window}; +use iced::{Length, Subscription}; +use iced::{theme, window}; pub use settings::Settings; use std::borrow::Cow; -use std::cell::RefCell; -use std::rc::Rc; +use std::{cell::RefCell, rc::Rc}; #[cold] pub(crate) fn iced_settings( @@ -773,6 +773,7 @@ impl ApplicationExt for App { .focused(focused) .maximized(maximized) .sharp_corners(sharp_corners) + .transparent(content_container) .title(&core.window.header_title) .on_drag(crate::Action::Cosmic(Action::Drag)) .on_right_click(crate::Action::Cosmic(Action::ShowWindowMenu)) diff --git a/src/applet/column.rs b/src/applet/column.rs index 1ec9c731..bb16f085 100644 --- a/src/applet/column.rs +++ b/src/applet/column.rs @@ -1,11 +1,15 @@ //! Distribute content vertically. use crate::iced; use iced::core::alignment::{self, Alignment}; -use iced::core::event::{self, Event}; +use iced::core::event::Event; +use iced::core::layout; +use iced::core::mouse; +use iced::core::overlay; +use iced::core::renderer; use iced::core::widget::{Operation, Tree}; use iced::core::{ Clipboard, Element, Layout, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, Widget, - layout, mouse, overlay, renderer, widget, + widget, }; /// A container that distributes its contents vertically. diff --git a/src/applet/mod.rs b/src/applet/mod.rs index e16b0303..d1ae6e87 100644 --- a/src/applet/mod.rs +++ b/src/applet/mod.rs @@ -1,31 +1,33 @@ #[cfg(feature = "applet-token")] pub mod token; -use crate::app::{BootData, BootDataInner, cosmic, iced_settings}; -use crate::cctk::sctk; -use crate::theme::{self, Button, THEME, system_dark, system_light}; -use crate::widget::autosize::{self, Autosize, autosize}; -use crate::widget::column::Column; -use crate::widget::row::Row; -use crate::widget::space::{horizontal, vertical}; -use crate::widget::{self, layer_container}; -use crate::{Application, Element, Renderer}; +use crate::app::{BootData, BootDataInner, cosmic}; +use crate::{ + Application, Element, Renderer, + app::iced_settings, + cctk::sctk, + theme::{self, Button, THEME, system_dark, system_light}, + widget::{ + self, + autosize::{self, Autosize, autosize}, + layer_container, + }, +}; pub use cosmic_panel_config; use cosmic_panel_config::{CosmicPanelBackground, PanelAnchor, PanelSize}; -use iced::alignment::{Alignment, Horizontal, Vertical}; -use iced::widget::Container; -use iced::{self, Color, Length, Limits, Rectangle, window}; +use iced::{ + self, Color, Length, Limits, Rectangle, + alignment::{Alignment, Horizontal, Vertical}, + widget::Container, + window, +}; use iced_core::{Padding, Shadow}; use iced_runtime::platform_specific::wayland::popup::{SctkPopupSettings, SctkPositioner}; use iced_widget::Text; use sctk::reexports::protocols::xdg::shell::client::xdg_positioner::{Anchor, Gravity}; -use std::borrow::Cow; use std::cell::RefCell; -use std::num::NonZeroU32; -use std::rc::Rc; -use std::sync::LazyLock; -use std::time::Duration; +use std::{borrow::Cow, num::NonZeroU32, rc::Rc, sync::LazyLock, time::Duration}; use tracing::info; pub mod column; @@ -211,12 +213,6 @@ impl Context { icon: widget::icon::Handle, ) -> crate::widget::Button<'a, Message> { let suggested = self.suggested_size(icon.symbolic); - let (applet_padding_major_axis, applet_padding_minor_axis) = self.suggested_padding(true); - let (horizontal_padding, vertical_padding) = if self.is_horizontal() { - (applet_padding_major_axis, applet_padding_minor_axis) - } else { - (applet_padding_minor_axis, applet_padding_major_axis) - }; let symbolic = icon.symbolic; let icon = widget::icon(icon) .class(if symbolic { @@ -459,10 +455,8 @@ impl Context { &self, content: impl Into>, ) -> Autosize<'a, Message, crate::Theme, crate::Renderer> { - let force_configured = matches!(&self.panel_type, PanelType::Other(n) if n.is_empty()); let w = autosize(content, AUTOSIZE_MAIN_ID.clone()); let mut limits = Limits::NONE; - let suggested_window_size = self.suggested_window_size(); if let Some(width) = self .suggested_bounds @@ -573,7 +567,7 @@ pub fn run(flags: App::Flags) -> iced::Result { // window_settings = window_settings.clone(); core.main_window = Some(iced_core::window::Id::RESERVED); } - let mut app = iced::daemon( + let app = iced::daemon( BootData(Rc::new(RefCell::new(Some(BootDataInner:: { flags, core, diff --git a/src/applet/row.rs b/src/applet/row.rs index 888c68ef..3ac9f7e0 100644 --- a/src/applet/row.rs +++ b/src/applet/row.rs @@ -3,10 +3,12 @@ use crate::iced; use iced::core::alignment::{self, Alignment}; use iced::core::event::Event; use iced::core::layout::{self, Layout}; +use iced::core::mouse; +use iced::core::overlay; +use iced::core::renderer; use iced::core::widget::{Operation, Tree}; use iced::core::{ - Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, Widget, mouse, - overlay, renderer, widget, + Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, Widget, widget, }; /// A container that distributes its contents horizontally. diff --git a/src/applet/token/subscription.rs b/src/applet/token/subscription.rs index 64be0ce2..07c528ea 100644 --- a/src/applet/token/subscription.rs +++ b/src/applet/token/subscription.rs @@ -1,12 +1,13 @@ use crate::iced; use cctk::sctk::reexports::calloop; -use futures::channel::mpsc::{UnboundedReceiver, unbounded}; -use futures::{SinkExt, StreamExt}; +use futures::{ + SinkExt, StreamExt, + channel::mpsc::{UnboundedReceiver, unbounded}, +}; use iced::Subscription; -use iced_futures::{futures, stream}; -use std::fmt::Debug; -use std::hash::Hash; -use std::thread::JoinHandle; +use iced_futures::futures; +use iced_futures::stream; +use std::{fmt::Debug, hash::Hash, thread::JoinHandle}; use super::wayland_handler::wayland_handler; diff --git a/src/applet/token/wayland_handler.rs b/src/applet/token/wayland_handler.rs index 3bbaf573..3db84fc4 100644 --- a/src/applet/token/wayland_handler.rs +++ b/src/applet/token/wayland_handler.rs @@ -1,20 +1,27 @@ -use std::os::fd::{FromRawFd, RawFd}; -use std::os::unix::net::UnixStream; +use std::os::{ + fd::{FromRawFd, RawFd}, + unix::net::UnixStream, +}; use super::subscription::{TokenRequest, TokenUpdate}; -use cctk::sctk::activation::{RequestData, RequestDataExt}; -use cctk::sctk::reexports::calloop; -use cctk::sctk::reexports::calloop_wayland_source::WaylandSource; -use cctk::sctk::seat::{SeatHandler, SeatState}; -use cctk::sctk::{self}; -use cctk::wayland_client::protocol::wl_seat::WlSeat; -use cctk::wayland_client::protocol::wl_surface::WlSurface; -use cctk::wayland_client::{self}; +use cctk::{ + sctk::{ + self, + activation::{RequestData, RequestDataExt}, + reexports::{calloop, calloop_wayland_source::WaylandSource}, + seat::{SeatHandler, SeatState}, + }, + wayland_client::{ + self, + protocol::{wl_seat::WlSeat, wl_surface::WlSurface}, + }, +}; use iced_futures::futures::channel::mpsc::UnboundedSender; -use sctk::activation::{ActivationHandler, ActivationState}; -use sctk::registry::{ProvidesRegistryState, RegistryState}; -use wayland_client::globals::registry_queue_init; -use wayland_client::{Connection, QueueHandle}; +use sctk::{ + activation::{ActivationHandler, ActivationState}, + registry::{ProvidesRegistryState, RegistryState}, +}; +use wayland_client::{Connection, QueueHandle, globals::registry_queue_init}; struct AppData { exit: bool, @@ -164,18 +171,7 @@ pub(crate) fn wayland_handler( if app_data.exit { break; } - - if let Err(why) = event_loop.dispatch(None, &mut app_data) { - if let calloop::Error::IoError(ref why) = why - && why.kind() == std::io::ErrorKind::BrokenPipe - { - tracing::info!("Connection to panel has ended. The applet will now exit with it."); - break; - } - - tracing::error!(?why, "dispatch error on Wayland connection to panel"); - break; - } + event_loop.dispatch(None, &mut app_data).unwrap(); } } diff --git a/src/dbus_activation.rs b/src/dbus_activation.rs index 880db634..10857fac 100644 --- a/src/dbus_activation.rs +++ b/src/dbus_activation.rs @@ -1,15 +1,17 @@ // Copyright 2024 System76 // SPDX-License-Identifier: MPL-2.0 -use crate::ApplicationExt; -use iced::Subscription; -use iced_futures::futures::SinkExt; -use iced_futures::futures::channel::mpsc::{Receiver, Sender}; -use std::any::TypeId; -use std::collections::HashMap; -use url::Url; -use zbus::zvariant::Value; -use zbus::{interface, proxy}; +use { + crate::ApplicationExt, + iced::Subscription, + iced_futures::futures::{ + SinkExt, + channel::mpsc::{Receiver, Sender}, + }, + std::{any::TypeId, collections::HashMap}, + url::Url, + zbus::{interface, proxy, zvariant::Value}, +}; #[cold] pub fn subscription() -> Subscription> { diff --git a/src/desktop.rs b/src/desktop.rs index 11276960..0a49eb8a 100644 --- a/src/desktop.rs +++ b/src/desktop.rs @@ -876,8 +876,7 @@ trait SystemdManger { #[cfg(all(test, not(windows)))] mod tests { use super::*; - use std::path::{Path, PathBuf}; - use std::{env, fs}; + use std::{env, fs, path::Path, path::PathBuf}; use tempfile::tempdir; struct EnvVarGuard { diff --git a/src/lib.rs b/src/lib.rs index 9c31506d..b1f893af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ #![allow(clippy::module_name_repetitions)] #![cfg_attr(target_os = "redox", feature(lazy_cell))] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] /// Recommended default imports. pub mod prelude { diff --git a/src/localize.rs b/src/localize.rs index d63d9706..95a31655 100644 --- a/src/localize.rs +++ b/src/localize.rs @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-only -use i18n_embed::fluent::{FluentLanguageLoader, fluent_language_loader}; -use i18n_embed::{DefaultLocalizer, LanguageLoader, Localizer}; +use i18n_embed::{ + DefaultLocalizer, LanguageLoader, Localizer, + fluent::{FluentLanguageLoader, fluent_language_loader}, +}; use rust_embed::RustEmbed; use std::sync::{LazyLock, OnceLock}; diff --git a/src/process.rs b/src/process.rs index e2cb0f70..2b6c4e0e 100644 --- a/src/process.rs +++ b/src/process.rs @@ -5,7 +5,7 @@ use smol::io::AsyncReadExt; use std::io; use std::os::fd::OwnedFd; -use std::process::{Command, Stdio}; +use std::process::{Command, Stdio, exit}; #[cfg(feature = "tokio")] use tokio::io::AsyncReadExt; @@ -56,33 +56,24 @@ pub async fn spawn(mut command: Command) -> Option { match unsafe { libc::fork() } { // Parent process - fork_pid @ 1..=i32::MAX => { + 1.. => { // Drop copy of write end, then read PID from pipe drop(write); let pid = read_from_pipe(read).await; - _ = rustix::process::waitpid( - rustix::process::Pid::from_raw(fork_pid), - rustix::process::WaitOptions::empty(), - ); + // wait to prevent zombie + _ = rustix::process::wait(rustix::process::WaitOptions::empty()); pid } // Child process 0 => { let _res = rustix::process::setsid(); - let exit_status = if let Ok(child) = command.spawn() { + if let Ok(child) = command.spawn() { // Write PID to pipe let _ = rustix::io::write(write, &child.id().to_be_bytes()); - 0 - } else { - 1 - }; - - // # Safety - // Required for child fork to exit without affecting the parent. - unsafe { - libc::_exit(exit_status); } + + exit(0) } ..=-1 => { diff --git a/src/surface/action.rs b/src/surface/action.rs index 16816fff..72dbad66 100644 --- a/src/surface/action.rs +++ b/src/surface/action.rs @@ -5,8 +5,7 @@ use super::Action; use crate::Application; use iced::window; -use std::any::Any; -use std::sync::Arc; +use std::{any::Any, sync::Arc}; /// Used to produce a destroy popup message from within a widget. #[cfg(all(feature = "wayland", target_os = "linux"))] diff --git a/src/surface/mod.rs b/src/surface/mod.rs index 307b5275..513cb91f 100644 --- a/src/surface/mod.rs +++ b/src/surface/mod.rs @@ -3,8 +3,9 @@ pub mod action; -use iced::{Limits, Size, Task}; -use std::future::Future; +use iced::Limits; +use iced::Size; +use iced::Task; use std::sync::Arc; /// Ignore this message in your application. It will be intercepted. diff --git a/src/theme/mod.rs b/src/theme/mod.rs index a5ae5d4a..cf3beccb 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -7,9 +7,11 @@ pub mod portal; pub mod style; -use cosmic_config::{CosmicConfigEntry, config_subscription}; -use cosmic_theme::{Component, LayeredTheme, Spacing, ThemeMode}; -use iced_futures::Subscription; +use cosmic_config::CosmicConfigEntry; +use cosmic_theme::Component; +use cosmic_theme::LayeredTheme; +use cosmic_theme::Spacing; +use cosmic_theme::ThemeMode; use iced_runtime::{Appearance, DefaultStyle}; use std::sync::{Arc, LazyLock, Mutex}; pub use style::*; diff --git a/src/theme/style/button.rs b/src/theme/style/button.rs index f84c9e97..c405455b 100644 --- a/src/theme/style/button.rs +++ b/src/theme/style/button.rs @@ -6,8 +6,10 @@ use cosmic_theme::Component; use iced_core::{Background, Color}; -use crate::theme::TRANSPARENT_COMPONENT; -use crate::widget::button::{Catalog, Style}; +use crate::{ + theme::TRANSPARENT_COMPONENT, + widget::button::{Catalog, Style}, +}; #[derive(Default)] pub enum Button { @@ -148,7 +150,7 @@ pub fn appearance( } Button::ListItem(radii) => { corner_radii = radii; - let (background, text, icon) = color(&cosmic.list_button); + let (background, text, icon) = color(&cosmic.background.component); if selected { appearance.background = @@ -195,7 +197,7 @@ impl Catalog for crate::Theme { return active(focused, self); } - appearance(self, focused, selected, false, style, move |component| { + let mut s = appearance(self, focused, selected, false, style, move |component| { let text_color = if matches!( style, Button::Icon | Button::IconVertical | Button::HeaderBar @@ -207,7 +209,14 @@ impl Catalog for crate::Theme { }; (component.base.into(), text_color, text_color) - }) + }); + + if let Button::ListItem(_) = style + && !selected { + s.background = None; + } + + s } fn disabled(&self, style: &Self::Class) -> Style { @@ -235,7 +244,7 @@ impl Catalog for crate::Theme { return hovered(focused, self); } - appearance( + let mut s = appearance( self, focused || matches!(style, Button::Image), selected, @@ -254,7 +263,14 @@ impl Catalog for crate::Theme { (component.hover.into(), text_color, text_color) }, - ) + ); + + if let Button::ListItem(_) = style + && !selected { + s.background = None; + } + + s } fn pressed(&self, focused: bool, selected: bool, style: &Self::Class) -> Style { diff --git a/src/theme/style/iced.rs b/src/theme/style/iced.rs index 8f9fa461..746503e3 100644 --- a/src/theme/style/iced.rs +++ b/src/theme/style/iced.rs @@ -5,17 +5,18 @@ use crate::theme::{CosmicComponent, TRANSPARENT_COMPONENT, Theme}; use cosmic_theme::composite::over; -use iced::overlay::menu; -use iced::theme::Base; -use iced::widget::slider::{self, Rail}; -use iced::widget::{ - button as iced_button, checkbox as iced_checkbox, combo_box, container as iced_container, - pane_grid, pick_list, progress_bar, radio, rule, scrollable, svg, toggler, +use iced::{ + overlay::menu, + theme::Base, + widget::{ + button as iced_button, checkbox as iced_checkbox, combo_box, container as iced_container, + pane_grid, pick_list, progress_bar, radio, rule, scrollable, + slider::{self, Rail}, + svg, toggler, + }, }; use iced_core::{Background, Border, Color, Shadow, Vector}; -use iced_widget::pane_grid::Highlight; -use iced_widget::scrollable::AutoScroll; -use iced_widget::{text_editor, text_input}; +use iced_widget::{pane_grid::Highlight, scrollable::AutoScroll, text_editor, text_input}; use palette::WithAlpha; use std::rc::Rc; @@ -1338,16 +1339,9 @@ impl iced_widget::text::Catalog for Theme { match class { Text::Accent => iced_widget::text::Style { color: Some(self.cosmic().accent_text_color().into()), - ..Default::default() - }, - Text::Default => iced_widget::text::Style { - color: None, - ..Default::default() - }, - Text::Color(c) => iced_widget::text::Style { - color: Some(*c), - ..Default::default() }, + Text::Default => iced_widget::text::Style { color: None }, + Text::Color(c) => iced_widget::text::Style { color: Some(*c) }, Text::Custom(f) => f(self), } } diff --git a/src/theme/style/menu_bar.rs b/src/theme/style/menu_bar.rs index db6e0ba1..ed0e657a 100644 --- a/src/theme/style/menu_bar.rs +++ b/src/theme/style/menu_bar.rs @@ -71,7 +71,7 @@ impl StyleSheet for Theme { background: component.base.into(), border_width: 1.0, bar_border_radius: cosmic.corner_radii.radius_xl, - menu_border_radius: cosmic.corner_radii.radius_s, + menu_border_radius: cosmic.corner_radii.radius_s.map(|x| x + 2.0), border_color: component.divider.into(), background_expand: [1; 4], path: component.hover.into(), diff --git a/src/theme/style/segmented_button.rs b/src/theme/style/segmented_button.rs index 45fcc0b8..de8b5782 100644 --- a/src/theme/style/segmented_button.rs +++ b/src/theme/style/segmented_button.rs @@ -3,13 +3,10 @@ //! Contains stylesheet implementation for [`crate::widget::segmented_button`]. -use crate::theme::Theme; -use crate::widget::segmented_button::{ - Appearance, ItemAppearance, ItemStatusAppearance, StyleSheet, -}; +use crate::widget::segmented_button::{Appearance, ItemAppearance, StyleSheet}; +use crate::{theme::Theme, widget::segmented_button::ItemStatusAppearance}; use iced::Border; -use iced_core::Background; -use iced_core::border::Radius; +use iced_core::{Background, border::Radius}; use palette::WithAlpha; #[derive(Default)] @@ -146,8 +143,7 @@ mod horizontal { use crate::widget::segmented_button::{ItemAppearance, ItemStatusAppearance}; use cosmic_theme::{Component, Container}; use iced::Border; - use iced_core::Background; - use iced_core::border::Radius; + use iced_core::{Background, border::Radius}; use palette::WithAlpha; pub fn tab_bar(cosmic: &cosmic_theme::Theme, container: &Container) -> Appearance { @@ -254,8 +250,7 @@ mod vertical { use crate::widget::segmented_button::{ItemAppearance, ItemStatusAppearance}; use cosmic_theme::{Component, Container}; use iced::Border; - use iced_core::Background; - use iced_core::border::Radius; + use iced_core::{Background, border::Radius}; use palette::WithAlpha; pub fn tab_bar(cosmic: &cosmic_theme::Theme, container: &Container) -> Appearance { diff --git a/src/widget/about.rs b/src/widget/about.rs index 490b0378..9b21e93a 100644 --- a/src/widget/about.rs +++ b/src/widget/about.rs @@ -1,6 +1,8 @@ -use crate::iced::{Alignment, Length}; -use crate::widget::{self, list}; -use crate::{Apply, Element, fl}; +use crate::{ + Apply, Element, fl, + iced::{Alignment, Length}, + widget::{self, list}, +}; use std::rc::Rc; #[derive(Debug, Default, Clone, derive_setters::Setters)] diff --git a/src/widget/aspect_ratio.rs b/src/widget/aspect_ratio.rs index 5cd8b9c0..577bea95 100644 --- a/src/widget/aspect_ratio.rs +++ b/src/widget/aspect_ratio.rs @@ -3,10 +3,13 @@ use iced::Size; use iced::widget::Container; use iced_core::event::Event; +use iced_core::layout; +use iced_core::mouse; +use iced_core::overlay; +use iced_core::renderer; use iced_core::widget::Tree; use iced_core::{ Alignment, Clipboard, Element, Layout, Length, Padding, Rectangle, Shell, Vector, Widget, - layout, mouse, overlay, renderer, }; pub use iced_widget::container::{Catalog, Style}; diff --git a/src/widget/autosize.rs b/src/widget/autosize.rs index c52367db..69fd9c83 100644 --- a/src/widget/autosize.rs +++ b/src/widget/autosize.rs @@ -1,11 +1,12 @@ //! Autosize Container, which will resize the window to its contents. use iced_core::event::{self, Event}; +use iced_core::layout; +use iced_core::mouse; +use iced_core::overlay; +use iced_core::renderer; use iced_core::widget::{Id, Operation, Tree}; -use iced_core::{ - Clipboard, Element, Layout, Length, Rectangle, Shell, Vector, Widget, layout, mouse, overlay, - renderer, -}; +use iced_core::{Clipboard, Element, Layout, Length, Rectangle, Shell, Vector, Widget}; pub use iced_widget::container::{Catalog, Style}; pub fn autosize<'a, Message: 'static, Theme, E>( diff --git a/src/widget/button/icon.rs b/src/widget/button/icon.rs index 47713536..a0e06323 100644 --- a/src/widget/button/icon.rs +++ b/src/widget/button/icon.rs @@ -3,13 +3,9 @@ use super::{Builder, ButtonClass}; use crate::Element; -use crate::widget::icon::Handle; -use crate::widget::tooltip; +use crate::widget::{icon::Handle, tooltip}; use apply::Apply; -use iced_core::font::Weight; -use iced_core::text::LineHeight; -use iced_core::widget::Id; -use iced_core::{Alignment, Length, Padding}; +use iced_core::{Alignment, Length, Padding, font::Weight, text::LineHeight, widget::Id}; use std::borrow::Cow; pub type Button<'a, Message> = Builder<'a, Message, Icon>; diff --git a/src/widget/button/image.rs b/src/widget/button/image.rs index 915cc532..c5a40fd5 100644 --- a/src/widget/button/image.rs +++ b/src/widget/button/image.rs @@ -2,12 +2,11 @@ // SPDX-License-Identifier: MPL-2.0 use super::Builder; -use crate::Element; -use crate::widget::image::Handle; -use crate::widget::{self}; -use iced_core::font::Weight; -use iced_core::widget::Id; -use iced_core::{Length, Padding}; +use crate::{ + Element, + widget::{self, image::Handle}, +}; +use iced_core::{Length, Padding, font::Weight, widget::Id}; use std::borrow::Cow; pub type Button<'a, Message> = Builder<'a, Message, Image<'a, Handle, Message>>; diff --git a/src/widget/button/link.rs b/src/widget/button/link.rs index e6f8ac7e..9bcd7487 100644 --- a/src/widget/button/link.rs +++ b/src/widget/button/link.rs @@ -3,15 +3,14 @@ //! Hyperlink button widget -use super::{Builder, ButtonClass}; +use super::Builder; +use super::ButtonClass; use crate::Element; use crate::prelude::*; use crate::widget::icon::{self, Handle}; use crate::widget::{button, row, tooltip}; -use iced_core::font::Weight; use iced_core::text::LineHeight; -use iced_core::widget::Id; -use iced_core::{Alignment, Length, Padding}; +use iced_core::{Alignment, Length, Padding, font::Weight, widget::Id}; use std::borrow::Cow; pub type Button<'a, Message> = Builder<'a, Message, Hyperlink>; diff --git a/src/widget/button/style.rs b/src/widget/button/style.rs index f8df8c62..21afa08b 100644 --- a/src/widget/button/style.rs +++ b/src/widget/button/style.rs @@ -2,8 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 //! Change the apperance of a button. -use iced_core::border::Radius; -use iced_core::{Background, Color, Vector}; +use iced_core::{Background, Color, Vector, border::Radius}; use crate::theme::THEME; diff --git a/src/widget/button/text.rs b/src/widget/button/text.rs index 55623ff8..71cd1f53 100644 --- a/src/widget/button/text.rs +++ b/src/widget/button/text.rs @@ -4,10 +4,7 @@ use super::{Builder, ButtonClass}; use crate::widget::{icon, row, tooltip}; use crate::{Apply, Element}; -use iced_core::font::Weight; -use iced_core::text::LineHeight; -use iced_core::widget::Id; -use iced_core::{Alignment, Length, Padding}; +use iced_core::{Alignment, Length, Padding, font::Weight, text::LineHeight, widget::Id}; use std::borrow::Cow; pub type Button<'a, Message> = Builder<'a, Message, Text>; diff --git a/src/widget/button/widget.rs b/src/widget/button/widget.rs index e6b83d7b..cdb2b5d6 100644 --- a/src/widget/button/widget.rs +++ b/src/widget/button/widget.rs @@ -11,12 +11,15 @@ use iced_runtime::{Action, Task, keyboard, task}; use iced_core::event::Event; use iced_core::renderer::{self, Quad, Renderer}; +use iced_core::touch; use iced_core::widget::Operation; use iced_core::widget::tree::{self, Tree}; use iced_core::{ - Background, Border, Clipboard, Color, Layout, Length, Padding, Point, Rectangle, Shadow, Shell, - Vector, Widget, layout, mouse, overlay, svg, touch, + Background, Clipboard, Color, Layout, Length, Padding, Point, Rectangle, Shell, Vector, Widget, }; +use iced_core::{Border, mouse}; +use iced_core::{Shadow, overlay}; +use iced_core::{layout, svg}; use iced_renderer::core::widget::operation; use crate::theme::THEME; @@ -641,8 +644,10 @@ impl<'a, Message: 'a + Clone> Widget state: &Tree, p: mouse::Cursor, ) -> iced_accessibility::A11yTree { - use iced_accessibility::accesskit::{Action, Node, NodeId, Rect, Role}; - use iced_accessibility::{A11yNode, A11yTree}; + use iced_accessibility::{ + A11yNode, A11yTree, + accesskit::{Action, Node, NodeId, Rect, Role}, + }; // TODO why is state None sometimes? if matches!(state.state, iced_core::widget::tree::State::None) { tracing::info!("Button state is missing."); diff --git a/src/widget/calendar.rs b/src/widget/calendar.rs index 35632c3a..91c601d3 100644 --- a/src/widget/calendar.rs +++ b/src/widget/calendar.rs @@ -8,8 +8,10 @@ use crate::widget::{button, column, grid, icon, row, text}; use apply::Apply; use iced::alignment::Vertical; use iced_core::{Alignment, Length}; -use jiff::ToSpan; -use jiff::civil::{Date, Weekday}; +use jiff::{ + ToSpan, + civil::{Date, Weekday}, +}; /// A widget that displays an interactive calendar. pub fn calendar( diff --git a/src/widget/cards.rs b/src/widget/cards.rs index 4d6770fa..72300cac 100644 --- a/src/widget/cards.rs +++ b/src/widget/cards.rs @@ -1,18 +1,23 @@ //! An expandable stack of cards use std::time::Duration; -use crate::anim; -use crate::widget::card::style::Style; -use crate::widget::icon::{self, Handle}; -use crate::widget::{button, column, row, text}; +use crate::{ + anim, + widget::{ + button, + card::style::Style, + column, + icon::{self, Handle}, + row, text, + }, +}; use float_cmp::approx_eq; use iced::widget; -use iced_core::border::Radius; -use iced_core::id::Id; -use iced_core::layout::Node; -use iced_core::renderer::Quad; -use iced_core::widget::{Tree, tree}; -use iced_core::{Border, Element, Event, Length, Shadow, Size, Vector, Widget, window}; +use iced_core::{ + Border, Element, Event, Length, Shadow, Size, Vector, Widget, border::Radius, id::Id, + layout::Node, renderer::Quad, widget::Tree, +}; +use iced_core::{widget::tree, window}; const ICON_SIZE: u16 = 16; const TOP_SPACING: u16 = 4; diff --git a/src/widget/color_picker/mod.rs b/src/widget/color_picker/mod.rs index 879cc604..0de31fd6 100644 --- a/src/widget/color_picker/mod.rs +++ b/src/widget/color_picker/mod.rs @@ -12,9 +12,7 @@ use std::time::{Duration, Instant}; use crate::Element; use crate::theme::iced::Slider; use crate::theme::{Button, THEME}; -use crate::widget::button::Catalog; -use crate::widget::segmented_button::Entity; -use crate::widget::{container, slider}; +use crate::widget::{button::Catalog, container, segmented_button::Entity, slider}; use derive_setters::Setters; use iced::Task; use iced_core::event::Event; @@ -27,8 +25,10 @@ use iced_core::{ }; use iced_widget::slider::HandleShape; -use iced_widget::space::{horizontal, vertical}; -use iced_widget::{Row, canvas, column, row, scrollable}; +use iced_widget::{ + Row, canvas, column, row, scrollable, + space::{horizontal, vertical}, +}; use palette::{FromColor, RgbHue}; use super::divider::horizontal; diff --git a/src/widget/context_drawer/overlay.rs b/src/widget/context_drawer/overlay.rs index 01f5cfcf..39b34217 100644 --- a/src/widget/context_drawer/overlay.rs +++ b/src/widget/context_drawer/overlay.rs @@ -5,7 +5,8 @@ use crate::Element; use iced::advanced::layout::{self, Layout}; use iced::advanced::widget::{self, Operation}; -use iced::advanced::{Clipboard, Shell, overlay, renderer}; +use iced::advanced::{Clipboard, Shell}; +use iced::advanced::{overlay, renderer}; use iced::{Event, Point, Size, mouse}; use iced_core::{Renderer, touch}; diff --git a/src/widget/context_drawer/widget.rs b/src/widget/context_drawer/widget.rs index 9a7448eb..7420738c 100644 --- a/src/widget/context_drawer/widget.rs +++ b/src/widget/context_drawer/widget.rs @@ -6,10 +6,11 @@ use crate::widget::{self, LayerContainer, button, column, container, icon, row, use crate::{Apply, Element, Renderer, Theme, fl}; use std::borrow::Cow; +use iced_core::Alignment; use iced_core::event::Event; use iced_core::widget::{Operation, Tree}; use iced_core::{ - Alignment, Clipboard, Layout, Length, Rectangle, Shell, Vector, Widget, layout, mouse, + Clipboard, Layout, Length, Rectangle, Shell, Vector, Widget, layout, mouse, overlay as iced_overlay, renderer, }; diff --git a/src/widget/context_menu.rs b/src/widget/context_menu.rs index 9256c954..37fce504 100644 --- a/src/widget/context_menu.rs +++ b/src/widget/context_menu.rs @@ -79,8 +79,7 @@ impl ContextMenu<'_, Message> { my_state: &mut LocalState, ) { if self.window_id != window::Id::NONE && self.on_surface_action.is_some() { - use crate::surface::action::destroy_popup; - use crate::widget::menu::Menu; + use crate::{surface::action::destroy_popup, widget::menu::Menu}; use iced_runtime::platform_specific::wayland::popup::{ SctkPopupSettings, SctkPositioner, }; diff --git a/src/widget/dialog.rs b/src/widget/dialog.rs index 72ab11f4..7d084626 100644 --- a/src/widget/dialog.rs +++ b/src/widget/dialog.rs @@ -1,5 +1,8 @@ -use crate::iced::{Length, Pixels}; -use crate::{Element, style, theme, widget}; +use crate::{ + Element, + iced::{Length, Pixels}, + style, theme, widget, +}; use std::borrow::Cow; pub fn dialog<'a, Message>() -> Dialog<'a, Message> { diff --git a/src/widget/dnd_destination.rs b/src/widget/dnd_destination.rs index afe135bc..683a766b 100644 --- a/src/widget/dnd_destination.rs +++ b/src/widget/dnd_destination.rs @@ -1,17 +1,29 @@ -use std::borrow::Cow; -use std::sync::atomic::{AtomicU64, Ordering}; +use std::{ + borrow::Cow, + sync::atomic::{AtomicU64, Ordering}, +}; use iced::Vector; -use crate::Element; -use crate::widget::{Id, Widget}; +use crate::{ + Element, + widget::{Id, Widget}, +}; -use iced::clipboard::dnd::{self, DndAction, DndDestinationRectangle, DndEvent, OfferEvent}; -use iced::clipboard::mime::AllowedMimeTypes; -use iced::id::Internal; -use iced::{Event, Length, Rectangle, event, mouse, overlay}; -use iced_core::widget::{Tree, tree}; -use iced_core::{self, Clipboard, Shell, layout}; +use iced::{ + Event, Length, Rectangle, + clipboard::{ + dnd::{self, DndAction, DndDestinationRectangle, DndEvent, OfferEvent}, + mime::AllowedMimeTypes, + }, + event, + id::Internal, + mouse, overlay, +}; +use iced_core::{ + self, Clipboard, Shell, layout, + widget::{Tree, tree}, +}; pub fn dnd_destination<'a, Message: 'static>( child: impl Into>, diff --git a/src/widget/dnd_source.rs b/src/widget/dnd_source.rs index 3cc9fa71..170d6940 100644 --- a/src/widget/dnd_source.rs +++ b/src/widget/dnd_source.rs @@ -1,14 +1,19 @@ use std::any::Any; -use iced_core::widget::Operation; -use iced_core::window; +use iced_core::{widget::Operation, window}; -use crate::Element; -use crate::widget::{Id, Widget, container}; -use iced::clipboard::dnd::{DndAction, DndEvent, SourceEvent}; -use iced::{Event, Length, Point, Rectangle, Vector, event, mouse, overlay}; -use iced_core::widget::{Tree, tree}; -use iced_core::{self, Clipboard, Shell, layout, renderer}; +use crate::{ + Element, + widget::{Id, Widget, container}, +}; +use iced::{ + Event, Length, Point, Rectangle, Vector, + clipboard::dnd::{DndAction, DndEvent, SourceEvent}, mouse, overlay, +}; +use iced_core::{ + self, Clipboard, Shell, layout, renderer, + widget::{Tree, tree}, +}; pub fn dnd_source< 'a, diff --git a/src/widget/dropdown/menu/appearance.rs b/src/widget/dropdown/menu/appearance.rs index 2c32c011..d1bed21c 100644 --- a/src/widget/dropdown/menu/appearance.rs +++ b/src/widget/dropdown/menu/appearance.rs @@ -3,8 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 AND MIT //! Change the appearance of menus. -use iced_core::border::Radius; -use iced_core::{Background, Color}; +use iced_core::{Background, Color, border::Radius}; /// The appearance of a menu. #[derive(Debug, Clone, Copy)] diff --git a/src/widget/dropdown/multi/widget.rs b/src/widget/dropdown/multi/widget.rs index c7a46592..dd877def 100644 --- a/src/widget/dropdown/multi/widget.rs +++ b/src/widget/dropdown/multi/widget.rs @@ -9,9 +9,9 @@ use iced_core::event::Event; use iced_core::text::{self, Text}; use iced_core::widget::tree::{self, Tree}; use iced_core::{ - Clipboard, Layout, Length, Padding, Pixels, Rectangle, Shadow, Shell, Size, Vector, Widget, - alignment, keyboard, layout, mouse, overlay, renderer, svg, touch, + Clipboard, Layout, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, Widget, }; +use iced_core::{Shadow, alignment, keyboard, layout, mouse, overlay, renderer, svg, touch}; use iced_widget::pick_list; pub use iced_widget::pick_list::{Catalog, Style}; diff --git a/src/widget/dropdown/widget.rs b/src/widget/dropdown/widget.rs index ebcf175a..0ba04c15 100644 --- a/src/widget/dropdown/widget.rs +++ b/src/widget/dropdown/widget.rs @@ -12,9 +12,9 @@ use iced_core::event::Event; use iced_core::text::{self, Paragraph, Text}; use iced_core::widget::tree::{self, Tree}; use iced_core::{ - Clipboard, Layout, Length, Padding, Pixels, Rectangle, Shadow, Shell, Size, Vector, Widget, - alignment, keyboard, layout, mouse, overlay, renderer, svg, touch, + Clipboard, Layout, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, Widget, }; +use iced_core::{Shadow, alignment, keyboard, layout, mouse, overlay, renderer, svg, touch}; use iced_widget::pick_list::{self, Catalog}; use std::borrow::Cow; use std::hash::{DefaultHasher, Hash, Hasher}; diff --git a/src/widget/frames.rs b/src/widget/frames.rs index bf985ce2..a542cec6 100644 --- a/src/widget/frames.rs +++ b/src/widget/frames.rs @@ -2,12 +2,14 @@ //! Based on use std::ffi::OsStr; +use std::fmt; +use std::io; use std::path::Path; use std::time::{Duration, Instant}; -use std::{fmt, io}; use ::image as image_rs; -use iced::{Task, mouse}; +use iced::Task; +use iced::mouse; use iced_core::image::Renderer as ImageRenderer; use iced_core::mouse::Cursor; use iced_core::widget::{Tree, tree}; diff --git a/src/widget/header_bar.rs b/src/widget/header_bar.rs index 82a7e8e9..0fcbc6c6 100644 --- a/src/widget/header_bar.rs +++ b/src/widget/header_bar.rs @@ -5,8 +5,7 @@ use crate::cosmic_theme::{Density, Spacing}; use crate::{Element, theme, widget}; use apply::Apply; use derive_setters::Setters; -use iced_core::widget::tree; -use iced_core::{Length, Size, Vector, Widget, layout, text}; +use iced_core::{Length, Size, Vector, Widget, layout, text, widget::tree}; use std::borrow::Cow; #[must_use] @@ -401,7 +400,6 @@ impl<'a, Message: Clone + 'static> HeaderBar<'a, Message> { space_xxs, .. } = theme::spacing(); - let is_ssd = self.is_ssd; // Take ownership of the regions to be packed. let mut start = std::mem::take(&mut self.start); @@ -419,7 +417,7 @@ impl<'a, Message: Clone + 'static> HeaderBar<'a, Message> { WindowControlsPosition::Start => start.insert(0, controls), } - let padding = if is_ssd { + let padding = if self.is_ssd { [2, 8, 2, 8] } else { match ( @@ -464,7 +462,7 @@ impl<'a, Message: Clone + 'static> HeaderBar<'a, Message> { .class(theme::Container::HeaderBar { focused: self.focused, sharp_corners: self.sharp_corners, - transparent: if is_ssd { false } else { true }, + transparent: self.transparent, }) .height(Length::Fixed(32.0 + padding[0] as f32 + padding[2] as f32)) .padding(padding) diff --git a/src/widget/icon/named.rs b/src/widget/icon/named.rs index 89050301..dfd66cf5 100644 --- a/src/widget/icon/named.rs +++ b/src/widget/icon/named.rs @@ -2,10 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 use super::{Handle, Icon}; -use std::borrow::Cow; -use std::ffi::OsStr; -use std::path::PathBuf; -use std::sync::Arc; +use std::{borrow::Cow, ffi::OsStr, path::PathBuf, sync::Arc}; #[derive(Debug, Clone, Default, Hash)] /// Fallback icon to use if the icon was not found. @@ -39,10 +36,6 @@ pub struct Named { /// Prioritizes SVG over PNG pub prefer_svg: bool, - - /// Extra directories to search as flat paths before the icon theme chain. - #[setters(skip)] - pub extra_paths: Vec, } impl Named { @@ -56,30 +49,19 @@ impl Named { size: None, scale: None, prefer_svg: symbolic, - extra_paths: Vec::new(), } } - pub fn with_extra_paths(mut self, paths: Vec) -> Self { - self.extra_paths = paths; - self - } - #[cfg(all(unix, not(target_os = "macos")))] #[must_use] pub fn path(self) -> Option { let name = &*self.name; let fallback = &self.fallback; - let extra_paths = &self.extra_paths; let locate = |theme: &str, name| { let mut lookup = freedesktop_icons::lookup(name) .with_theme(theme.as_ref()) .with_cache(); - if !extra_paths.is_empty() { - lookup = lookup.with_extra_paths(extra_paths); - } - if let Some(scale) = self.scale { lookup = lookup.with_scale(scale); } diff --git a/src/widget/id_container.rs b/src/widget/id_container.rs index 6b0d13ce..8f280cab 100644 --- a/src/widget/id_container.rs +++ b/src/widget/id_container.rs @@ -1,9 +1,10 @@ -use iced_core::event::{self, Event}; +use iced_core::event::Event; +use iced_core::layout; +use iced_core::mouse; +use iced_core::overlay; +use iced_core::renderer; use iced_core::widget::{Id, Operation, Tree}; -use iced_core::{ - Clipboard, Element, Layout, Length, Rectangle, Shell, Vector, Widget, layout, mouse, overlay, - renderer, -}; +use iced_core::{Clipboard, Element, Layout, Length, Rectangle, Shell, Vector, Widget}; pub use iced_widget::container::{Catalog, Style}; pub fn id_container<'a, Message: 'static, Theme, E>( diff --git a/src/widget/layer_container.rs b/src/widget/layer_container.rs index 3958b03c..577261f6 100644 --- a/src/widget/layer_container.rs +++ b/src/widget/layer_container.rs @@ -1,11 +1,14 @@ use crate::Theme; use cosmic_theme::LayeredTheme; use iced::widget::Container; -use iced_core::event::{self, Event}; +use iced_core::event::Event; +use iced_core::layout; +use iced_core::mouse; +use iced_core::overlay; +use iced_core::renderer; use iced_core::widget::Tree; use iced_core::{ Alignment, Clipboard, Element, Layout, Length, Padding, Rectangle, Shell, Vector, Widget, - layout, mouse, overlay, renderer, }; pub use iced_widget::container::{Catalog, Style}; diff --git a/src/widget/list/list_column.rs b/src/widget/list/list_column.rs index 9e4204cc..4ef3fc01 100644 --- a/src/widget/list/list_column.rs +++ b/src/widget/list/list_column.rs @@ -2,8 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 use crate::widget::container::Catalog; -use crate::widget::space::vertical; -use crate::widget::{button, column, container, divider, row}; +use crate::widget::{button, column, container, divider, row, space::vertical}; use crate::{Apply, Element, theme}; use iced::{Length, Padding}; diff --git a/src/widget/menu/flex.rs b/src/widget/menu/flex.rs index e4a32870..09dab466 100644 --- a/src/widget/menu/flex.rs +++ b/src/widget/menu/flex.rs @@ -1,9 +1,11 @@ // From iced_aw, license MIT -use iced_core::Widget; -use iced_core::widget::Tree; -use iced_widget::core::layout::{Limits, Node}; -use iced_widget::core::{Alignment, Element, Padding, Point, Size, renderer}; +use iced_core::{Widget, widget::Tree}; +use iced_widget::core::{ + Alignment, Element, Padding, Point, Size, + layout::{Limits, Node}, + renderer, +}; use crate::widget::RcElementWrapper; diff --git a/src/widget/menu/key_bind.rs b/src/widget/menu/key_bind.rs index ef87b344..8b4ed227 100644 --- a/src/widget/menu/key_bind.rs +++ b/src/widget/menu/key_bind.rs @@ -1,4 +1,3 @@ -use iced_core::keyboard::key::{Code, Physical}; use iced_core::keyboard::{Key, Modifiers}; use std::fmt; @@ -28,102 +27,28 @@ pub struct KeyBind { } impl KeyBind { - /// Checks if the given key and modifiers match the `KeyBind`, with an - /// optional fallback to the physical key position for non-Latin keyboard - /// layouts. + /// Checks if the given key and modifiers match the `KeyBind`. /// /// # Arguments /// /// * `modifiers` - A `Modifiers` instance representing the current active modifiers. /// * `key` - A reference to the `Key` that is being checked. - /// * `physical_key` - An optional reference to the physical key position, - /// used as a fallback when the logical `key` does not match (e.g. on - /// Cyrillic or other non-Latin layouts). Can be `None` for keys where - /// the physical position is not relevant (e.g. `Key::Named`). /// /// # Returns /// /// * `bool` - `true` if the key and modifiers match the `KeyBind`, `false` otherwise. - pub fn matches( - &self, - modifiers: Modifiers, - key: &Key, - physical_key: Option<&Physical>, - ) -> bool { - let key_eq = self.key_eq(key) - || physical_key - .and_then(physical_key_to_latin) - .is_some_and(|latin| self.key_eq(&latin)); + pub fn matches(&self, modifiers: Modifiers, key: &Key) -> bool { + let key_eq = match (key, &self.key) { + // CapsLock and Shift change the case of Key::Character, so we compare these in a case insensitive way + (Key::Character(a), Key::Character(b)) => a.eq_ignore_ascii_case(b), + (a, b) => a.eq(b), + }; key_eq && modifiers.logo() == self.modifiers.contains(&Modifier::Super) && modifiers.control() == self.modifiers.contains(&Modifier::Ctrl) && modifiers.alt() == self.modifiers.contains(&Modifier::Alt) && modifiers.shift() == self.modifiers.contains(&Modifier::Shift) } - - fn key_eq(&self, key: &Key) -> bool { - match (key, &self.key) { - // CapsLock and Shift change the case of Key::Character, so we compare these in a case insensitive way - (Key::Character(a), Key::Character(b)) => a.eq_ignore_ascii_case(b), - (a, b) => a.eq(b), - } - } -} - -/// Converts a physical key code to the corresponding US-layout Latin `Key`. -/// -/// This mapping is intentionally limited to keys that may produce different -/// characters on non-Latin keyboard layouts (letters and punctuation). Keys -/// like digits are not included because they remain the same across layouts. -/// -/// Only used as a fallback when the primary key comparison in -/// [`KeyBind::matches`] does not match. -fn physical_key_to_latin(physical_key: &Physical) -> Option { - let code = match physical_key { - Physical::Code(code) => code, - Physical::Unidentified(_) => return None, - }; - let ch = match code { - Code::KeyA => "a", - Code::KeyB => "b", - Code::KeyC => "c", - Code::KeyD => "d", - Code::KeyE => "e", - Code::KeyF => "f", - Code::KeyG => "g", - Code::KeyH => "h", - Code::KeyI => "i", - Code::KeyJ => "j", - Code::KeyK => "k", - Code::KeyL => "l", - Code::KeyM => "m", - Code::KeyN => "n", - Code::KeyO => "o", - Code::KeyP => "p", - Code::KeyQ => "q", - Code::KeyR => "r", - Code::KeyS => "s", - Code::KeyT => "t", - Code::KeyU => "u", - Code::KeyV => "v", - Code::KeyW => "w", - Code::KeyX => "x", - Code::KeyY => "y", - Code::KeyZ => "z", - Code::Minus => "-", - Code::Equal => "=", - Code::BracketLeft => "[", - Code::BracketRight => "]", - Code::Backslash => "\\", - Code::Semicolon => ";", - Code::Quote => "'", - Code::Backquote => "`", - Code::Comma => ",", - Code::Period => ".", - Code::Slash => "/", - _ => return None, - }; - Some(Key::Character(ch.into())) } impl fmt::Display for KeyBind { diff --git a/src/widget/menu/menu_bar.rs b/src/widget/menu/menu_bar.rs index 3843c349..981053b3 100644 --- a/src/widget/menu/menu_bar.rs +++ b/src/widget/menu/menu_bar.rs @@ -1,14 +1,14 @@ // From iced_aw, license MIT //! A widget that handles menu trees -use std::collections::HashMap; -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; -use super::menu_inner::{ - CloseCondition, Direction, ItemHeight, ItemWidth, Menu, MenuState, PathHighlight, +use super::{ + menu_inner::{ + CloseCondition, Direction, ItemHeight, ItemWidth, Menu, MenuState, PathHighlight, + }, + menu_tree::MenuTree, }; -use super::menu_tree::MenuTree; -use crate::Renderer; #[cfg(all( feature = "multi-window", feature = "wayland", @@ -16,21 +16,25 @@ use crate::Renderer; feature = "surface-message" ))] use crate::app::cosmic::{WINDOWING_SYSTEM, WindowingSystem}; -use crate::style::menu_bar::StyleSheet; -use crate::widget::RcWrapper; -use crate::widget::dropdown::menu::{self, State}; -use crate::widget::menu::menu_inner::init_root_menu; +use crate::{ + Renderer, + style::menu_bar::StyleSheet, + widget::{ + RcWrapper, + menu::menu_inner::init_root_menu, + }, +}; -use iced::event::Status; use iced::{Point, Shadow, Vector, window}; use iced_core::Border; -use iced_widget::core::layout::{Limits, Node}; -use iced_widget::core::mouse::{self, Cursor}; -use iced_widget::core::renderer::{self, Renderer as IcedRenderer}; -use iced_widget::core::widget::{Tree, tree}; use iced_widget::core::{ Alignment, Clipboard, Element, Layout, Length, Padding, Rectangle, Shell, Widget, event, - overlay, touch, + layout::{Limits, Node}, + mouse::{self, Cursor}, + overlay, + renderer::{self, Renderer as IcedRenderer}, + touch, + widget::{Tree, tree}, }; /// A `MenuBar` collects `MenuTree`s and handles all the layout, event processing, and drawing. @@ -570,8 +574,7 @@ where viewport: &Rectangle, ) { use event::Event::{Mouse, Touch}; - use mouse::Button::Left; - use mouse::Event::ButtonReleased; + use mouse::{Button::Left, Event::ButtonReleased}; use touch::Event::{FingerLifted, FingerLost}; process_root_events( @@ -738,7 +741,7 @@ where tree: &'b mut Tree, layout: Layout<'b>, _renderer: &Renderer, - viewport: &Rectangle, + _viewport: &Rectangle, translation: Vector, ) -> Option> { #[cfg(all( diff --git a/src/widget/menu/menu_inner.rs b/src/widget/menu/menu_inner.rs index c534c5b7..af0b3add 100644 --- a/src/widget/menu/menu_inner.rs +++ b/src/widget/menu/menu_inner.rs @@ -1,11 +1,9 @@ // From iced_aw, license MIT //! Menu tree overlay -use std::borrow::Cow; -use std::sync::Arc; +use std::{borrow::Cow, sync::Arc}; -use super::menu_bar::MenuBarState; -use super::menu_tree::MenuTree; +use super::{menu_bar::MenuBarState, menu_tree::MenuTree}; #[cfg(all( feature = "multi-window", feature = "wayland", @@ -17,12 +15,12 @@ use crate::style::menu_bar::StyleSheet; use iced::window; use iced_core::{Border, Renderer as IcedRenderer, Shadow, Widget}; -use iced_widget::core::layout::{Limits, Node}; -use iced_widget::core::mouse::{self, Cursor}; -use iced_widget::core::widget::Tree; use iced_widget::core::{ - Clipboard, Layout, Length, Padding, Point, Rectangle, Shell, Size, Vector, event, overlay, - renderer, touch, + Clipboard, Layout, Length, Padding, Point, Rectangle, Shell, Size, Vector, event, + layout::{Limits, Node}, + mouse::{self, Cursor}, + overlay, renderer, touch, + widget::Tree, }; /// The condition of when to close a menu @@ -561,9 +559,10 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> { shell: &mut Shell<'_, Message>, ) -> Option<(usize, MenuState)> { use event::Event::{Mouse, Touch}; - use event::Status::{Captured, Ignored}; - use mouse::Button::Left; - use mouse::Event::{ButtonPressed, ButtonReleased, CursorMoved, WheelScrolled}; + use mouse::{ + Button::Left, + Event::{ButtonPressed, ButtonReleased, CursorMoved, WheelScrolled}, + }; use touch::Event::{FingerLifted, FingerMoved, FingerPressed}; if !self @@ -579,7 +578,7 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> { let viewport_size = viewport.size(); let overlay_offset = Point::ORIGIN - viewport.position(); let overlay_cursor = view_cursor.position().unwrap_or_default() - overlay_offset; - let menu_roots = match &mut self.menu_roots { + let _menu_roots = match &mut self.menu_roots { Cow::Borrowed(_) => panic!(), Cow::Owned(o) => o.as_mut_slice(), }; @@ -949,7 +948,7 @@ impl Widget, cursor: mouse::Cursor, @@ -967,21 +966,21 @@ impl Widget Widget( ) where Message: Clone, { - use event::Status::{Captured, Ignored}; + use mouse::ScrollDelta; menu.tree.inner.with_data_mut(|state| { diff --git a/src/widget/menu/menu_tree.rs b/src/widget/menu/menu_tree.rs index efcf9800..41cf1dff 100644 --- a/src/widget/menu/menu_tree.rs +++ b/src/widget/menu/menu_tree.rs @@ -234,7 +234,6 @@ pub fn menu_items< color.alpha *= 0.75; TextStyle { color: Some(color.into()), - ..Default::default() } } let key_class = theme::Text::Custom(key_style); diff --git a/src/widget/mod.rs b/src/widget/mod.rs index 5764ab44..d83a74e2 100644 --- a/src/widget/mod.rs +++ b/src/widget/mod.rs @@ -152,7 +152,7 @@ pub use dialog::{Dialog, dialog}; pub mod divider { /// Horizontal variant of a divider. pub mod horizontal { - use iced::widget::{Rule, rule}; + use iced::{widget::Rule, widget::rule}; /// Horizontal divider with default thickness #[must_use] diff --git a/src/widget/nav_bar.rs b/src/widget/nav_bar.rs index b7391abb..ad6f9206 100644 --- a/src/widget/nav_bar.rs +++ b/src/widget/nav_bar.rs @@ -6,9 +6,10 @@ //! For details on the model, see the [`segmented_button`] module for more details. use apply::Apply; -use iced::clipboard::dnd::DndAction; -use iced::clipboard::mime::AllowedMimeTypes; -use iced::{Background, Length}; +use iced::{ + Background, Length, + clipboard::{dnd::DndAction, mime::AllowedMimeTypes}, +}; use iced_core::{Border, Color, Shadow}; use crate::widget::{Container, Icon, container, menu, scrollable, segmented_button}; diff --git a/src/widget/popover.rs b/src/widget/popover.rs index 138d5a19..7ca9eeff 100644 --- a/src/widget/popover.rs +++ b/src/widget/popover.rs @@ -4,11 +4,15 @@ //! A container which displays an overlay when a popup widget is attached. use iced::widget; -use iced_core::event::{self, Event}; +use iced_core::event::Event; +use iced_core::layout; +use iced_core::mouse; +use iced_core::overlay; +use iced_core::renderer; +use iced_core::touch; use iced_core::widget::{Operation, Tree}; use iced_core::{ - Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Size, Vector, Widget, layout, - mouse, overlay, renderer, touch, + Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Size, Vector, Widget, }; pub use iced_widget::container::{Catalog, Style}; diff --git a/src/widget/progress_bar/animation.rs b/src/widget/progress_bar/animation.rs deleted file mode 100644 index a9d52831..00000000 --- a/src/widget/progress_bar/animation.rs +++ /dev/null @@ -1,115 +0,0 @@ -use crate::anim::smootherstep; -use iced::time::Instant; -use std::time::Duration; - -const LAG: f32 = 0.1; - -#[derive(Default)] -pub struct Progress { - pub current: f32, - target: Option, - last: Option, -} - -impl Progress { - /// Smoothly chases `target` using exponential decay. - /// Returns `true` if a redraw should be requested. - pub fn update(&mut self, target: f32, now: Instant) -> bool { - // Don't animate on start - let Some(last) = self.last else { - self.current = target; - self.target = Some(target); - self.last = Some(now); - return false; - }; - - // Sync animation clock when target changes - if self.target != Some(target) { - self.target = Some(target); - self.last = Some(now); - return true; - } - - let dt = (now - last).as_secs_f32(); - self.last = Some(now); - let diff = target - self.current; - - if diff.abs() > 0.001 { - self.current += diff * (1.0 - (-dt / LAG).exp()); - true - } else { - self.current = target; - false - } - } -} - -#[derive(Clone, Copy)] -pub struct Animation { - expanding: bool, - start: Instant, - last: Instant, - offset: u32, -} - -impl Default for Animation { - fn default() -> Self { - let now = Instant::now(); - Self { - expanding: true, - start: now, - last: now, - offset: 0, - } - } -} - -impl Animation { - pub fn timed_transition( - &self, - cycle_duration: Duration, - period: Duration, - wrap: f32, - now: Instant, - ) -> Self { - let additional = - ((now - self.last).as_secs_f32() / period.as_secs_f32() * u32::MAX as f32) as u32; - let new_offset = self.offset.wrapping_add(additional); - - if !cycle_duration.is_zero() && now.duration_since(self.start) > cycle_duration { - let offset = if self.expanding { - new_offset - } else { - new_offset.wrapping_add((wrap * u32::MAX as f32) as u32) - }; - Self { - expanding: !self.expanding, - start: now, - last: now, - offset, - } - } else { - Self { - last: now, - offset: new_offset, - ..*self - } - } - } - - pub fn bar_positions(&self, cycle_duration: Duration, min: f32, wrap: f32) -> (f32, f32) { - let offset = self.offset as f32 / u32::MAX as f32; - let progress = if !cycle_duration.is_zero() { - smootherstep( - self.last.duration_since(self.start).as_secs_f32() / cycle_duration.as_secs_f32(), - ) - } else { - 1.0 - }; - if self.expanding { - (offset, offset + min + wrap * progress) - } else { - (offset + wrap * progress, offset + min + wrap) - } - } -} diff --git a/src/widget/progress_bar/circular.rs b/src/widget/progress_bar/circular.rs index 3a3fedc4..fa8c38fe 100644 --- a/src/widget/progress_bar/circular.rs +++ b/src/widget/progress_bar/circular.rs @@ -1,10 +1,15 @@ //! Show a circular progress indicator. -use super::animation::{Animation, Progress}; use super::style::StyleSheet; +use crate::anim::smootherstep; +use iced::advanced::layout; +use iced::advanced::renderer; use iced::advanced::widget::tree::{self, Tree}; -use iced::advanced::{self, Clipboard, Layout, Shell, Widget, layout, renderer}; +use iced::advanced::{self, Clipboard, Layout, Shell, Widget}; +use iced::mouse; +use iced::time::Instant; use iced::widget::canvas; -use iced::{Element, Event, Length, Radians, Rectangle, Renderer, Size, Vector, mouse, window}; +use iced::window; +use iced::{Element, Event, Length, Radians, Rectangle, Renderer, Size, Vector}; use std::f32::consts::PI; use std::time::Duration; @@ -18,9 +23,9 @@ where { size: f32, bar_height: f32, - style: Theme::Style, + style: ::Style, cycle_duration: Duration, - period: Duration, + rotation_duration: Duration, progress: Option, } @@ -33,9 +38,9 @@ where Circular { size: 40.0, bar_height: 4.0, - style: Theme::Style::default(), + style: ::Style::default(), cycle_duration: Duration::from_millis(1500), - period: Duration::from_secs(2), + rotation_duration: Duration::from_secs(2), progress: None, } } @@ -53,7 +58,7 @@ where } /// Sets the style variant of this [`Circular`]. - pub fn style(mut self, style: Theme::Style) -> Self { + pub fn style(mut self, style: ::Style) -> Self { self.style = style; self } @@ -64,10 +69,10 @@ where self } - /// Sets the base period of this [`Circular`]. This is the duration that a full rotation - /// would take if the cycle duration were set to 0.0 (no expanding or contracting) - pub fn period(mut self, duration: Duration) -> Self { - self.period = duration; + /// Sets the base rotation duration of this [`Circular`]. This is the duration that a full + /// rotation would take if the cycle rotation were set to 0.0 (no expanding or contracting) + pub fn rotation_duration(mut self, duration: Duration) -> Self { + self.rotation_duration = duration; self } @@ -77,10 +82,10 @@ where self } - fn min_wrap(&self, track_radius: f32) -> (f32, f32) { + fn min_wrap_angle(&self, track_radius: f32) -> (f32, f32) { let cap_angle = self.bar_height / track_radius; let gap = MIN_ANGLE.0.max(cap_angle); - ((gap - cap_angle) / (2.0 * PI), 1.0 - gap / PI) + (gap - cap_angle, 2.0 * PI - gap * 2.0) } } @@ -93,11 +98,125 @@ where } } +#[derive(Clone, Copy)] +enum Animation { + Expanding { + start: Instant, + progress: f32, + rotation: u32, + last: Instant, + }, + Contracting { + start: Instant, + progress: f32, + rotation: u32, + last: Instant, + }, +} + +impl Default for Animation { + fn default() -> Self { + Self::Expanding { + start: Instant::now(), + progress: 0.0, + rotation: 0, + last: Instant::now(), + } + } +} + +impl Animation { + fn next(&self, additional_rotation: u32, wrap_angle: f32, now: Instant) -> Self { + match self { + Self::Expanding { rotation, .. } => Self::Contracting { + start: now, + progress: 0.0, + rotation: rotation.wrapping_add(additional_rotation), + last: now, + }, + Self::Contracting { rotation, .. } => Self::Expanding { + start: now, + progress: 0.0, + rotation: rotation.wrapping_add( + (f64::from((wrap_angle) / (2.0 * PI)) * f64::from(u32::MAX)) as u32, + ), + last: now, + }, + } + } + + fn start(&self) -> Instant { + match self { + Self::Expanding { start, .. } | Self::Contracting { start, .. } => *start, + } + } + + fn last(&self) -> Instant { + match self { + Self::Expanding { last, .. } | Self::Contracting { last, .. } => *last, + } + } + + fn timed_transition( + &self, + cycle_duration: Duration, + rotation_duration: Duration, + wrap_angle: f32, + now: Instant, + ) -> Self { + let elapsed = now.duration_since(self.start()); + let additional_rotation = ((now - self.last()).as_secs_f32() + / rotation_duration.as_secs_f32() + * (u32::MAX) as f32) as u32; + + match elapsed { + elapsed if elapsed > cycle_duration => self.next(additional_rotation, wrap_angle, now), + _ => self.with_elapsed(cycle_duration, additional_rotation, elapsed, now), + } + } + + fn with_elapsed( + &self, + cycle_duration: Duration, + additional_rotation: u32, + elapsed: Duration, + now: Instant, + ) -> Self { + let progress = elapsed.as_secs_f32() / cycle_duration.as_secs_f32(); + match self { + Self::Expanding { + start, rotation, .. + } => Self::Expanding { + start: *start, + progress, + rotation: rotation.wrapping_add(additional_rotation), + last: now, + }, + Self::Contracting { + start, rotation, .. + } => Self::Contracting { + start: *start, + progress, + rotation: rotation.wrapping_add(additional_rotation), + last: now, + }, + } + } + + fn rotation(&self) -> f32 { + match self { + Self::Expanding { rotation, .. } | Self::Contracting { rotation, .. } => { + *rotation as f32 / u32::MAX as f32 + } + } + } +} + #[derive(Default)] struct State { animation: Animation, cache: canvas::Cache, - progress: Progress, + progress: Option, } impl Widget for Circular @@ -141,21 +260,28 @@ where _viewport: &Rectangle, ) { let state = tree.state.downcast_mut::(); - if let Event::Window(window::Event::RedrawRequested(now)) = event { - if let Some(target) = self.progress { - if state.progress.update(target, *now) { - state.cache.clear(); - shell.request_redraw(); - } - } else { - let (_, wrap) = self.min_wrap(self.size / 2.0 - self.bar_height); - state.animation = - state - .animation - .timed_transition(self.cycle_duration, self.period, wrap, *now); + if self.progress.is_some() { + if !float_cmp::approx_eq!( + f32, + state.progress.unwrap_or_default(), + self.progress.unwrap_or_default() + ) { + state.progress = self.progress; state.cache.clear(); - shell.request_redraw(); } + return; + } + if let Event::Window(window::Event::RedrawRequested(now)) = event { + let (_, wrap_angle) = self.min_wrap_angle(self.size / 2.0 - self.bar_height); + state.animation = state.animation.timed_transition( + self.cycle_duration, + self.rotation_duration, + wrap_angle, + *now, + ); + + state.cache.clear(); + shell.request_redraw(); } } @@ -173,13 +299,11 @@ where let state = tree.state.downcast_ref::(); let bounds = layout.bounds(); - let custom_style = Theme::appearance(theme, &self.style, self.progress.is_some(), true); + let custom_style = + ::appearance(theme, &self.style, self.progress.is_some(), true); let geometry = state.cache.draw(renderer, bounds.size(), |frame| { let track_radius = frame.width() / 2.0 - self.bar_height; - if track_radius <= 0.0 { - return; - } let track_path = canvas::Path::circle(frame.center(), track_radius); frame.stroke( @@ -189,65 +313,133 @@ where .with_width(self.bar_height), ); - // Converts a track fraction to an angle in radians, with 0 being top of circle - let to_angle = |t: f32| t * 2.0 * PI - PI / 2.0; + if let Some(progress) = self.progress { + // outer border + if let Some(border_color) = custom_style.border_color { + let border_path = + canvas::Path::circle(frame.center(), track_radius + self.bar_height / 2.0); - let draw_cap = |frame: &mut canvas::Frame, t: f32, flip: bool| { - let angle = to_angle(t); - let center = frame.center() + Vector::new(angle.cos(), angle.sin()) * track_radius; - let (start_angle, end_angle) = if flip { - (angle - PI, angle) - } else { - (angle, angle + PI) - }; - let mut builder = canvas::path::Builder::new(); - builder.arc(canvas::path::Arc { - center, - radius: self.bar_height / 2.0, - start_angle: Radians(start_angle), - end_angle: Radians(end_angle), - }); - frame.fill(&builder.build(), custom_style.bar_color); - }; + frame.stroke( + &border_path, + canvas::Stroke::default() + .with_color(border_color) + .with_width(1.0), + ); + } - let draw_bar = |frame: &mut canvas::Frame, start: f32, end: f32| { + // inner border + if let Some(border_color) = custom_style.border_color { + let border_path = + canvas::Path::circle(frame.center(), track_radius - self.bar_height / 2.0); + + frame.stroke( + &border_path, + canvas::Stroke::default() + .with_color(border_color) + .with_width(1.0), + ); + } + + // bar let mut builder = canvas::path::Builder::new(); + builder.arc(canvas::path::Arc { center: frame.center(), radius: track_radius, - start_angle: Radians(to_angle(start)), - end_angle: Radians(to_angle(end)), + start_angle: Radians(-PI / 2.0), + end_angle: Radians(-PI / 2.0 + progress * 2.0 * PI), }); + + let bar_path = builder.build(); + frame.stroke( - &builder.build(), + &bar_path, canvas::Stroke::default() .with_color(custom_style.bar_color) .with_width(self.bar_height), ); - draw_cap(frame, end, false); - draw_cap(frame, start, true); - }; - if self.progress.is_some() { - if let Some(border_color) = custom_style.border_color { - for radius_offset in [self.bar_height / 2.0, -(self.bar_height / 2.0)] { - let border_path = - canvas::Path::circle(frame.center(), track_radius + radius_offset); - frame.stroke( - &border_path, - canvas::Stroke::default() - .with_color(border_color) - .with_width(1.0), - ); - } - } - draw_bar(frame, 0.0, state.progress.current); + let mut builder = canvas::path::Builder::new(); + + // get center of end of arc for rounded cap + let end_angle = -PI / 2.0 + progress * 2.0 * PI; + let end_center = + frame.center() + Vector::new(end_angle.cos(), end_angle.sin()) * track_radius; + builder.arc(canvas::path::Arc { + center: end_center, + radius: self.bar_height / 2.0, + start_angle: Radians(end_angle), + end_angle: Radians(end_angle + PI), + }); + + // get center of start of arc for rounded cap + let start_angle = -PI / 2.0; + let start_center = frame.center() + + Vector::new(start_angle.cos(), start_angle.sin()) * track_radius; + builder.arc(canvas::path::Arc { + center: start_center, + radius: self.bar_height / 2.0, + start_angle: Radians(start_angle - PI), + end_angle: Radians(start_angle), + }); + + let cap_path = builder.build(); + frame.fill(&cap_path, custom_style.bar_color); } else { - let (min, wrap) = self.min_wrap(track_radius); - let (start, end) = state - .animation - .bar_positions(self.cycle_duration, min, wrap); - draw_bar(frame, start, end); + let mut builder = canvas::path::Builder::new(); + + let start = state.animation.rotation() * 2.0 * PI; + let (min_angle, wrap_angle) = self.min_wrap_angle(track_radius); + let (start_angle, end_angle) = match state.animation { + Animation::Expanding { progress, .. } => ( + start, + start + min_angle + wrap_angle * smootherstep(progress), + ), + Animation::Contracting { progress, .. } => ( + start + wrap_angle * smootherstep(progress), + start + min_angle + wrap_angle, + ), + }; + builder.arc(canvas::path::Arc { + center: frame.center(), + radius: track_radius, + start_angle: Radians(start_angle), + end_angle: Radians(end_angle), + }); + + let bar_path = builder.build(); + + frame.stroke( + &bar_path, + canvas::Stroke::default() + .with_color(custom_style.bar_color) + .with_width(self.bar_height), + ); + + let mut builder = canvas::path::Builder::new(); + + // get center of end of arc for rounded cap + let end_center = + frame.center() + Vector::new(end_angle.cos(), end_angle.sin()) * track_radius; + builder.arc(canvas::path::Arc { + center: end_center, + radius: self.bar_height / 2.0, + start_angle: Radians(end_angle), + end_angle: Radians(end_angle + PI), + }); + + // get center of start of arc for rounded cap + let start_center = frame.center() + + Vector::new(start_angle.cos(), start_angle.sin()) * track_radius; + builder.arc(canvas::path::Arc { + center: start_center, + radius: self.bar_height / 2.0, + start_angle: Radians(start_angle - PI), + end_angle: Radians(start_angle), + }); + + let cap_path = builder.build(); + frame.fill(&cap_path, custom_style.bar_color); } }); diff --git a/src/widget/progress_bar/linear.rs b/src/widget/progress_bar/linear.rs index 0ebe402f..226b2b5f 100644 --- a/src/widget/progress_bar/linear.rs +++ b/src/widget/progress_bar/linear.rs @@ -1,15 +1,19 @@ //! Show a linear progress indicator. -use super::animation::{Animation, Progress}; -use super::style::StyleSheet; +use iced::advanced::layout; +use iced::advanced::renderer::{self, Quad}; use iced::advanced::widget::tree::{self, Tree}; -use iced::advanced::{self, Clipboard, Layout, Shell, Widget, layout, renderer}; -use iced::{Background, Element, Event, Length, Pixels, Rectangle, Size, mouse, window}; +use iced::advanced::{self, Clipboard, Layout, Shell, Widget}; +use iced::mouse; +use iced::time::Instant; +use iced::window; +use iced::{Background, Element, Event, Length, Rectangle, Size}; + +use crate::anim::smootherstep; + +use super::style::StyleSheet; use std::time::Duration; -const MIN_LENGTH: f32 = 0.15; -const WRAP_LENGTH: f32 = 0.618; // avoids animation repetition - #[must_use] pub struct Linear where @@ -19,10 +23,7 @@ where girth: Length, style: Theme::Style, cycle_duration: Duration, - period: Duration, progress: Option, - markers: Vec, - segment_spacing: f32, } impl Linear @@ -36,10 +37,7 @@ where girth: Length::Fixed(4.0), style: Theme::Style::default(), cycle_duration: Duration::from_millis(1500), - period: Duration::from_secs(2), progress: None, - markers: Vec::new(), - segment_spacing: 0.0, } } @@ -67,38 +65,11 @@ where self } - /// Sets the base period of this [`Linear`]. This is the duration that a full traversal - /// would take if the cycle duration were set to 0.0 (no expanding or contracting) - pub fn period(mut self, duration: Duration) -> Self { - self.period = duration; - self - } - /// Override the default behavior by providing a determinate progress value between `0.0` and `1.0`. pub fn progress(mut self, progress: f32) -> Self { self.progress = Some(progress.clamp(0.0, 1.0)); self } - - /// Sets the markers of a determinate progress bar, which divide the bar into segments. - /// Each value is a progress fraction between `0.0` and `1.0 at which a visual gap is inserted. - pub fn markers(mut self, markers: impl Into>) -> Self { - let mut markers = markers.into(); - for bp in &mut markers { - *bp = bp.clamp(0.0, 1.0); - } - markers.sort_by(f32::total_cmp); - markers.dedup(); - - self.markers = markers; - self - } - - /// Sets the spacing between segments at each marker. - pub fn segment_spacing(mut self, spacing: impl Into) -> Self { - self.segment_spacing = spacing.into().0; - self - } } impl Default for Linear @@ -110,10 +81,63 @@ where } } -#[derive(Default)] -struct State { - animation: Animation, - progress: Progress, +#[derive(Clone, Copy)] +enum State { + Expanding { start: Instant, progress: f32 }, + Contracting { start: Instant, progress: f32 }, +} + +impl Default for State { + fn default() -> Self { + Self::Expanding { + start: Instant::now(), + progress: 0.0, + } + } +} + +impl State { + fn next(&self, now: Instant) -> Self { + match self { + Self::Expanding { .. } => Self::Contracting { + start: now, + progress: 0.0, + }, + Self::Contracting { .. } => Self::Expanding { + start: now, + progress: 0.0, + }, + } + } + + fn start(&self) -> Instant { + match self { + Self::Expanding { start, .. } | Self::Contracting { start, .. } => *start, + } + } + + fn timed_transition(&self, cycle_duration: Duration, now: Instant) -> Self { + let elapsed = now.duration_since(self.start()); + + match elapsed { + elapsed if elapsed > cycle_duration => self.next(now), + _ => self.with_elapsed(cycle_duration, elapsed), + } + } + + fn with_elapsed(&self, cycle_duration: Duration, elapsed: Duration) -> Self { + let progress = elapsed.as_secs_f32() / cycle_duration.as_secs_f32(); + match self { + Self::Expanding { start, .. } => Self::Expanding { + start: *start, + progress, + }, + Self::Contracting { start, .. } => Self::Contracting { + start: *start, + progress, + }, + } + } } impl Widget for Linear @@ -157,21 +181,16 @@ where shell: &mut Shell<'_, Message>, _viewport: &Rectangle, ) { + if self.progress.is_some() { + return; + } + let state = tree.state.downcast_mut::(); + if let Event::Window(window::Event::RedrawRequested(now)) = event { - if let Some(target) = self.progress { - if state.progress.update(target, *now) { - shell.request_redraw(); - } - } else { - state.animation = state.animation.timed_transition( - self.cycle_duration, - self.period, - WRAP_LENGTH, - *now, - ); - shell.request_redraw(); - } + *state = state.timed_transition(self.cycle_duration, *now); + + shell.request_redraw(); } } @@ -189,148 +208,88 @@ where let custom_style = theme.appearance(&self.style, self.progress.is_some(), false); let state = tree.state.downcast_ref::(); - let border_width = if custom_style.border_color.is_some() { - 1.0 - } else { - 0.0 - }; - let border_color = custom_style.border_color.unwrap_or(custom_style.bar_color); - let radius = custom_style.border_radius; + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { + x: bounds.x, + y: bounds.y, + width: bounds.width, + height: bounds.height, + }, + border: iced::Border { + width: if custom_style.border_color.is_some() { + 1.0 + } else { + 0.0 + }, + color: custom_style.border_color.unwrap_or(custom_style.bar_color), + radius: custom_style.border_radius.into(), + }, + snap: true, + ..renderer::Quad::default() + }, + Background::Color(custom_style.track_color), + ); - let mut draw_quad = |x: f32, width: f32, color: iced::Color, border: iced::Border| { - // don't draw if width is less than 0.1 pixels - if width * bounds.width > 0.1 { - renderer.fill_quad( + if let Some(progress) = self.progress { + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { + x: bounds.x, + y: bounds.y, + width: progress * bounds.width, + height: bounds.height, + }, + border: iced::Border { + width: 0., + color: iced::Color::TRANSPARENT, + radius: custom_style.border_radius.into(), + }, + snap: true, + ..renderer::Quad::default() + }, + Background::Color(custom_style.bar_color), + ); + } else { + match state { + State::Expanding { progress, .. } => renderer.fill_quad( renderer::Quad { bounds: Rectangle { - x: bounds.x + x * bounds.width, + x: bounds.x, y: bounds.y, - width: width * bounds.width, + width: smootherstep(*progress) * bounds.width, height: bounds.height, }, - border, + border: iced::Border { + width: 0., + color: iced::Color::TRANSPARENT, + radius: custom_style.border_radius.into(), + }, snap: true, ..renderer::Quad::default() }, - Background::Color(color), - ); - } - }; + Background::Color(custom_style.bar_color), + ), - if self.progress.is_some() { - let spacing = self.segment_spacing.max(1.0); - let radius_inner = radius.min(spacing); - - let gap = if self.markers.is_empty() { - 0.0 - } else { - spacing / bounds.width - }; - let drawable = 1.0 - gap * self.markers.len() as f32; - let num_segments = self.markers.len() + 1; - - let segment_bounds = |i: usize| { - let seg_lo = if i == 0 { 0.0 } else { self.markers[i - 1] }; - let seg_hi = if i == num_segments - 1 { - 1.0 - } else { - self.markers[i] - }; - (seg_lo, seg_hi) - }; - let get_radius = |i: usize| { - let r_left = if i == 0 { radius } else { radius_inner }; - let r_right = if i == num_segments - 1 { - radius - } else { - radius_inner - }; - [r_left, r_right, r_right, r_left].into() - }; - - // draw track segments - for i in 0..num_segments { - let (seg_lo, seg_hi) = segment_bounds(i); - let x_start = seg_lo * drawable + i as f32 * gap; - let x_width = (seg_hi - seg_lo) * drawable; - - draw_quad( - x_start, - x_width, - custom_style.track_color, - iced::Border { - width: border_width, - color: border_color, - radius: get_radius(i), + State::Contracting { progress, .. } => renderer.fill_quad( + Quad { + bounds: Rectangle { + x: bounds.x + smootherstep(*progress) * bounds.width, + y: bounds.y, + width: (1.0 - smootherstep(*progress)) * bounds.width, + height: bounds.height, + }, + border: iced::Border { + width: 0., + color: iced::Color::TRANSPARENT, + radius: custom_style.border_radius.into(), + }, + snap: true, + ..renderer::Quad::default() }, - ); + Background::Color(custom_style.bar_color), + ), } - - // draw bar segments - let current_p = state.progress.current; - for i in 0..num_segments { - let (seg_lo, seg_hi) = segment_bounds(i); - - // don't iterate over non-filled segments - if current_p < seg_lo { - break; - } - - let x_start = seg_lo * drawable + i as f32 * gap; - let x_width = (seg_hi - seg_lo) * drawable; - let fill = ((current_p - seg_lo) / (seg_hi - seg_lo)).clamp(0.0, 1.0); - - draw_quad( - x_start, - x_width * fill, - custom_style.bar_color, - iced::Border { - radius: get_radius(i), - ..iced::Border::default() - }, - ); - } - } else { - // draw track - draw_quad( - 0.0, - 1.0, - custom_style.track_color, - iced::Border { - width: border_width, - color: border_color, - radius: radius.into(), - }, - ); - - // draw bar - let (bar_start, bar_end) = - state - .animation - .bar_positions(self.cycle_duration, MIN_LENGTH, WRAP_LENGTH); - let length = bar_end - bar_start; - let start = bar_start % 1.0; - let right_width = (1.0 - start).min(length); - let left_width = length - right_width; - - draw_quad( - start, - right_width, - custom_style.bar_color, - iced::Border { - radius: radius.into(), - ..iced::Border::default() - }, - ); - draw_quad( - 0.0, - left_width, - custom_style.bar_color, - iced::Border { - radius: radius.into(), - ..iced::Border::default() - }, - ); } } } diff --git a/src/widget/progress_bar/mod.rs b/src/widget/progress_bar/mod.rs index cb24adac..4e277b0a 100644 --- a/src/widget/progress_bar/mod.rs +++ b/src/widget/progress_bar/mod.rs @@ -1,4 +1,3 @@ -mod animation; pub mod circular; pub mod linear; pub mod style; diff --git a/src/widget/radio.rs b/src/widget/radio.rs index f8e174e1..51ed00a4 100644 --- a/src/widget/radio.rs +++ b/src/widget/radio.rs @@ -1,11 +1,15 @@ //! Create choices using radio buttons. use crate::{Theme, theme}; use iced::border; -use iced_core::event::{self, Event}; +use iced_core::event::Event; +use iced_core::layout; +use iced_core::mouse; +use iced_core::overlay; +use iced_core::renderer; +use iced_core::touch; use iced_core::widget::tree::Tree; use iced_core::{ Border, Clipboard, Element, Layout, Length, Pixels, Rectangle, Shell, Size, Vector, Widget, - layout, mouse, overlay, renderer, touch, }; use iced_widget::radio as iced_radio; diff --git a/src/widget/rectangle_tracker/mod.rs b/src/widget/rectangle_tracker/mod.rs index 839fa9a7..f5969589 100644 --- a/src/widget/rectangle_tracker/mod.rs +++ b/src/widget/rectangle_tracker/mod.rs @@ -5,14 +5,14 @@ use iced::futures::channel::mpsc::UnboundedSender; use iced::widget::Container; pub use subscription::*; -use iced_core::event::{self, Event}; +use iced_core::event::Event; +use iced_core::layout; +use iced_core::mouse; +use iced_core::overlay; +use iced_core::renderer; use iced_core::widget::Tree; -use iced_core::{ - Alignment, Clipboard, Element, Layout, Length, Padding, Rectangle, Shell, Widget, layout, - mouse, overlay, renderer, -}; -use std::fmt::Debug; -use std::hash::Hash; +use iced_core::{Alignment, Clipboard, Element, Layout, Length, Padding, Rectangle, Shell, Widget}; +use std::{fmt::Debug, hash::Hash}; pub use iced_widget::container::{Catalog, Style}; diff --git a/src/widget/rectangle_tracker/subscription.rs b/src/widget/rectangle_tracker/subscription.rs index 22b42441..02fa4329 100644 --- a/src/widget/rectangle_tracker/subscription.rs +++ b/src/widget/rectangle_tracker/subscription.rs @@ -1,10 +1,13 @@ -use iced::Rectangle; -use iced::futures::channel::mpsc::{UnboundedReceiver, unbounded}; -use iced::futures::{StreamExt, stream}; +use iced::{ + Rectangle, + futures::{ + StreamExt, + channel::mpsc::{UnboundedReceiver, unbounded}, + stream, + }, +}; use iced_futures::Subscription; -use std::collections::HashMap; -use std::fmt::Debug; -use std::hash::Hash; +use std::{collections::HashMap, fmt::Debug, hash::Hash}; use super::RectangleTracker; diff --git a/src/widget/responsive_container.rs b/src/widget/responsive_container.rs index c8925cc2..14b7a030 100644 --- a/src/widget/responsive_container.rs +++ b/src/widget/responsive_container.rs @@ -1,12 +1,13 @@ //! Responsive Container, which will notify of size changes. use iced::{Limits, Size}; -use iced_core::event::{self, Event}; +use iced_core::event::Event; +use iced_core::layout; +use iced_core::mouse; +use iced_core::overlay; +use iced_core::renderer; use iced_core::widget::{Id, Operation, Tree, tree}; -use iced_core::{ - Clipboard, Element, Layout, Length, Rectangle, Shell, Vector, Widget, layout, mouse, overlay, - renderer, -}; +use iced_core::{Clipboard, Element, Layout, Length, Rectangle, Shell, Vector, Widget}; pub(crate) fn responsive_container<'a, Message: 'static, Theme, E>( content: E, diff --git a/src/widget/responsive_menu_bar.rs b/src/widget/responsive_menu_bar.rs index de323c13..86b7f0d2 100644 --- a/src/widget/responsive_menu_bar.rs +++ b/src/widget/responsive_menu_bar.rs @@ -2,8 +2,10 @@ use std::collections::HashMap; use apply::Apply; -use crate::widget::{button, icon, responsive_container}; -use crate::{Core, Element}; +use crate::{ + Core, Element, + widget::{button, icon, responsive_container}, +}; use super::menu::{self, ItemHeight, ItemWidth}; diff --git a/src/widget/segmented_button/widget.rs b/src/widget/segmented_button/widget.rs index 5e0b4f7f..9edf3e3b 100644 --- a/src/widget/segmented_button/widget.rs +++ b/src/widget/segmented_button/widget.rs @@ -25,11 +25,9 @@ use iced_core::id::Internal; use iced_core::mouse::ScrollDelta; use iced_core::text::{self, Ellipsize, LineHeight, Renderer as TextRenderer, Shaping, Wrapping}; use iced_core::widget::operation::Focusable; -use iced_core::widget::{self, Tree, operation, tree}; -use iced_core::{ - Border, Clipboard, Layout, Point, Renderer as IcedRenderer, Shadow, Shell, Text, Widget, - layout, renderer, -}; +use iced_core::widget::{self, operation, tree}; +use iced_core::{Border, Point, Renderer as IcedRenderer, Shadow, Text}; +use iced_core::{Clipboard, Layout, Shell, Widget, layout, renderer, widget::Tree}; use iced_runtime::{Action, task}; use slotmap::{Key, SecondaryMap}; use std::borrow::Cow; @@ -1448,8 +1446,6 @@ where state.context_cursor = cursor_position.position().unwrap_or_default(); state.menu_state.inner.with_data_mut(|data| { - // Clear stale MenuBounds from any previous context menu before opening a new one. - data.reset(); data.open = true; data.view_cursor = cursor_position; }); diff --git a/src/widget/settings/item.rs b/src/widget/settings/item.rs index 4eb5bb17..5abb464c 100644 --- a/src/widget/settings/item.rs +++ b/src/widget/settings/item.rs @@ -3,11 +3,12 @@ use std::borrow::Cow; -use crate::widget::{FlexRow, Row, column, container, flex_row, list, row, text}; -use crate::{Element, Theme, theme}; +use crate::{ + Element, Theme, theme, + widget::{FlexRow, Row, column, container, flex_row, list, row, text}, +}; use derive_setters::Setters; -use iced_core::Length; -use iced_core::text::Wrapping; +use iced_core::{Length, text::Wrapping}; use iced_widget::space; use taffy::AlignContent; diff --git a/src/widget/spin_button.rs b/src/widget/spin_button.rs index b2528861..3ff0e7bf 100644 --- a/src/widget/spin_button.rs +++ b/src/widget/spin_button.rs @@ -3,10 +3,13 @@ //! A control for incremental adjustments of a value. -use crate::widget::{button, column, container, icon, row, text}; -use crate::{Element, theme}; +use crate::{ + Element, theme, + widget::{button, column, container, icon, row, text}, +}; use apply::Apply; -use iced::{Alignment, Border, Length, Shadow}; +use iced::{Alignment, Length}; +use iced::{Border, Shadow}; use std::borrow::Cow; use std::ops::{Add, Sub}; diff --git a/src/widget/table/mod.rs b/src/widget/table/mod.rs index dfde3810..c546383c 100644 --- a/src/widget/table/mod.rs +++ b/src/widget/table/mod.rs @@ -2,9 +2,12 @@ //! pub mod model; -pub use model::category::{ItemCategory, ItemInterface}; -pub use model::selection::{MultiSelect, SingleSelect}; -pub use model::{Entity, Model}; +pub use model::{ + Entity, Model, + category::ItemCategory, + category::ItemInterface, + selection::{MultiSelect, SingleSelect}, +}; pub mod widget; pub use widget::compact::CompactTableView; pub use widget::standard::TableView; diff --git a/src/widget/table/model/entity.rs b/src/widget/table/model/entity.rs index 910ccd2f..51c60609 100644 --- a/src/widget/table/model/entity.rs +++ b/src/widget/table/model/entity.rs @@ -3,8 +3,10 @@ use slotmap::{SecondaryMap, SparseSecondaryMap}; -use super::category::{ItemCategory, ItemInterface}; -use super::{Entity, Model, Selectable}; +use super::{ + Entity, Model, Selectable, + category::{ItemCategory, ItemInterface}, +}; /// A newly-inserted item which may have additional actions applied to it. pub struct EntityMut< diff --git a/src/widget/table/model/mod.rs b/src/widget/table/model/mod.rs index f0e5e61c..749860f8 100644 --- a/src/widget/table/model/mod.rs +++ b/src/widget/table/model/mod.rs @@ -2,8 +2,10 @@ pub mod category; pub mod entity; pub mod selection; -use std::any::{Any, TypeId}; -use std::collections::{HashMap, VecDeque}; +use std::{ + any::{Any, TypeId}, + collections::{HashMap, VecDeque}, +}; use category::{ItemCategory, ItemInterface}; use entity::EntityMut; diff --git a/src/widget/table/model/selection.rs b/src/widget/table/model/selection.rs index 3e3d46b5..20a07248 100644 --- a/src/widget/table/model/selection.rs +++ b/src/widget/table/model/selection.rs @@ -3,8 +3,10 @@ //! Describes logic specific to the single-select and multi-select modes of a model. -use super::category::{ItemCategory, ItemInterface}; -use super::{Entity, Model}; +use super::{ + Entity, Model, + category::{ItemCategory, ItemInterface}, +}; use std::collections::HashSet; /// Describes a type that has selectable items. diff --git a/src/widget/table/widget/compact.rs b/src/widget/table/widget/compact.rs index 6d027caf..65ac9058 100644 --- a/src/widget/table/widget/compact.rs +++ b/src/widget/table/widget/compact.rs @@ -1,10 +1,14 @@ use derive_setters::Setters; -use crate::widget::table::model::category::{ItemCategory, ItemInterface}; -use crate::widget::table::model::selection::Selectable; -use crate::widget::table::model::{Entity, Model}; -use crate::widget::{self, container, menu}; -use crate::{Apply, Element, theme}; +use crate::widget::table::model::{ + Entity, Model, + category::{ItemCategory, ItemInterface}, + selection::Selectable, +}; +use crate::{ + Apply, Element, theme, + widget::{self, container, menu}, +}; use iced::{Alignment, Border, Padding}; #[derive(Setters)] diff --git a/src/widget/table/widget/standard.rs b/src/widget/table/widget/standard.rs index e21cd22f..c4cd648c 100644 --- a/src/widget/table/widget/standard.rs +++ b/src/widget/table/widget/standard.rs @@ -1,10 +1,14 @@ use derive_setters::Setters; -use crate::widget::table::model::category::{ItemCategory, ItemInterface}; -use crate::widget::table::model::selection::Selectable; -use crate::widget::table::model::{Entity, Model}; -use crate::widget::{self, container, divider, menu}; -use crate::{Apply, Element, theme}; +use crate::widget::table::model::{ + Entity, Model, + category::{ItemCategory, ItemInterface}, + selection::Selectable, +}; +use crate::{ + Apply, Element, theme, + widget::{self, container, divider, menu}, +}; use iced::{Alignment, Border, Length, Padding}; // THIS IS A PLACEHOLDER UNTIL A MORE SOPHISTICATED WIDGET CAN BE DEVELOPED diff --git a/src/widget/text_input/editor.rs b/src/widget/text_input/editor.rs index c9c2ca7a..b8144761 100644 --- a/src/widget/text_input/editor.rs +++ b/src/widget/text_input/editor.rs @@ -2,8 +2,7 @@ // Copyright 2023 System76 // SPDX-License-Identifier: MIT -use super::cursor::Cursor; -use super::value::Value; +use super::{cursor::Cursor, value::Value}; pub struct Editor<'a> { value: &'a mut Value, diff --git a/src/widget/text_input/input.rs b/src/widget/text_input/input.rs index 730fae25..903c81d1 100644 --- a/src/widget/text_input/input.rs +++ b/src/widget/text_input/input.rs @@ -28,14 +28,18 @@ use iced_core::overlay::Group; use iced_core::renderer::{self, Renderer as CoreRenderer}; use iced_core::text::{self, Paragraph, Renderer, Text}; use iced_core::time::{Duration, Instant}; +use iced_core::touch; use iced_core::widget::Id; use iced_core::widget::operation::{self, Operation}; use iced_core::widget::tree::{self, Tree}; +use iced_core::window; +use iced_core::{Background, alignment}; +use iced_core::{Border, Shadow, keyboard}; use iced_core::{ - Background, Border, Clipboard, Color, Element, Layout, Length, Padding, Pixels, Point, - Rectangle, Shadow, Shell, Size, Vector, Widget, alignment, keyboard, layout, overlay, touch, - window, + Clipboard, Color, Element, Layout, Length, Padding, Pixels, Point, Rectangle, Shell, Size, + Vector, Widget, }; +use iced_core::{layout, overlay}; use iced_runtime::{Action, Task, task}; thread_local! { diff --git a/src/widget/text_input/style.rs b/src/widget/text_input/style.rs index 52b98784..8af5e63e 100644 --- a/src/widget/text_input/style.rs +++ b/src/widget/text_input/style.rs @@ -4,8 +4,7 @@ //! Change the appearance of a text input. -use iced_core::border::Radius; -use iced_core::{Background, Color}; +use iced_core::{Background, Color, border::Radius}; /// The appearance of a text input. #[derive(Debug, Clone, Copy)] diff --git a/src/widget/toaster/mod.rs b/src/widget/toaster/mod.rs index 43acc5c1..bafaa9f9 100644 --- a/src/widget/toaster/mod.rs +++ b/src/widget/toaster/mod.rs @@ -6,13 +6,16 @@ use std::collections::VecDeque; use std::rc::Rc; -use crate::widget::{Column, container}; +use crate::widget::Column; +use crate::widget::container; use iced::Task; use iced_core::Element; -use slotmap::{SlotMap, new_key_type}; +use slotmap::SlotMap; +use slotmap::new_key_type; use widget::Toaster; -use super::{button, column, icon, row, text}; +use super::column; +use super::{button, icon, row, text}; mod widget; diff --git a/src/widget/toaster/widget.rs b/src/widget/toaster/widget.rs index 922c1433..9b6939e7 100644 --- a/src/widget/toaster/widget.rs +++ b/src/widget/toaster/widget.rs @@ -4,14 +4,16 @@ use iced::{Limits, Size}; use iced_core::layout::Node; -use iced_core::event::{self, Event}; +use iced_core::Element; +use iced_core::Overlay; +use iced_core::event::Event; +use iced_core::layout; +use iced_core::mouse; +use iced_core::overlay; use iced_core::renderer::{self}; use iced_core::widget::Operation; use iced_core::widget::tree::Tree; -use iced_core::{ - Clipboard, Element, Layout, Length, Overlay, Point, Rectangle, Shell, Vector, Widget, layout, - mouse, overlay, -}; +use iced_core::{Clipboard, Layout, Length, Point, Rectangle, Shell, Vector, Widget}; pub struct Toaster<'a, Message, Theme, Renderer> { toasts: Element<'a, Message, Theme, Renderer>, @@ -152,7 +154,7 @@ where translation, ) } else { - let bounds = layout.bounds(); + let _bounds = layout.bounds(); Some(overlay::Element::new(Box::new(ToasterOverlay::new( &mut state.children[1], diff --git a/src/widget/toggler.rs b/src/widget/toggler.rs index 2254759e..5e5bc2ee 100644 --- a/src/widget/toggler.rs +++ b/src/widget/toggler.rs @@ -1,18 +1,18 @@ //! Show toggle controls using togglers. -use std::time::{Duration, Instant}; +use std::time::Duration; use crate::{Element, anim}; -use iced_core::renderer::{self, Renderer}; -use iced_core::widget::{self, Tree, tree}; use iced_core::{ - Border, Clipboard, Event, Layout, Length, Pixels, Rectangle, Shell, Size, Widget, alignment, - event, layout, mouse, text, touch, window, + Border, Clipboard, Event, Layout, Length, Pixels, Rectangle, Shell, Size, Widget, alignment, layout, mouse, + renderer::{self, Renderer}, + text, touch, + widget::{self, Tree, tree}, + window, }; -use iced_widget::Id; -use iced_widget::toggler::Status; +use iced_widget::{Id, toggler::Status}; -pub use iced_widget::toggler::{Catalog, Style}; +pub use iced_widget::toggler::Catalog; pub fn toggler<'a, Message>(is_checked: bool) -> Toggler<'a, Message> { Toggler::new(is_checked) @@ -260,7 +260,7 @@ impl<'a, Message> Widget for Toggler<'a, shell.capture_event(); } } - Event::Window(window::Event::RedrawRequested(now)) => { + Event::Window(window::Event::RedrawRequested(_now)) => { state.anim.anim_done(self.duration); if state.anim.last_change.is_some() { shell.request_redraw(); @@ -370,7 +370,7 @@ impl<'a, Message> Widget for Toggler<'a, }, style.background, ); - let mut t = state.anim.t(self.duration, self.is_toggled); + let t = state.anim.t(self.duration, self.is_toggled); let toggler_foreground_bounds = Rectangle { x: bounds.x diff --git a/src/widget/wayland/tooltip/mod.rs b/src/widget/wayland/tooltip/mod.rs index aa80fad6..947d1e83 100644 --- a/src/widget/wayland/tooltip/mod.rs +++ b/src/widget/wayland/tooltip/mod.rs @@ -5,8 +5,7 @@ pub mod widget; // Copyright 2023 System76 // SPDX-License-Identifier: MPL-2.0 -use iced_core::border::Radius; -use iced_core::{Background, Color, Vector}; +use iced_core::{Background, Color, Vector, border::Radius}; use crate::theme::THEME; diff --git a/src/widget/wayland/tooltip/widget.rs b/src/widget/wayland/tooltip/widget.rs index 203a2010..0526e8db 100644 --- a/src/widget/wayland/tooltip/widget.rs +++ b/src/widget/wayland/tooltip/widget.rs @@ -13,24 +13,20 @@ use std::time::Duration; use iced::Task; use iced_runtime::core::widget::Id; -use iced_core::event::{self, Event}; +use iced_core::event::Event; +use iced_core::renderer; +use iced_core::touch; use iced_core::widget::Operation; use iced_core::widget::tree::{self, Tree}; use iced_core::{ - Background, Border, Clipboard, Color, Layout, Length, Padding, Point, Rectangle, Shadow, Shell, - Vector, Widget, layout, mouse, overlay, renderer, svg, touch, + Background, Clipboard, Color, Layout, Length, Padding, Point, Rectangle, Shell, Vector, Widget, }; +use iced_core::{Border, mouse}; +use iced_core::{Shadow, overlay}; +use iced_core::layout; pub use super::{Catalog, Style}; -/// Internally defines different button widget variants. -enum Variant { - Normal, - Image { - close_icon: svg::Handle, - on_remove: Option, - }, -} /// A generic button which emits a message when pressed. #[allow(missing_debug_implementations)] @@ -306,7 +302,7 @@ impl<'a, Message: 'static + Clone, TopLevelMessage: 'static + Clone> } let content_layout = layout.children().next().unwrap(); - let state = tree.state.downcast_ref::(); + let _state = tree.state.downcast_ref::(); let styling = theme.style(&self.style); @@ -460,7 +456,6 @@ pub fn update<'a, Message: Clone + 'static, TopLevelMessage: Clone + 'static>( shell.publish(on_leave.clone()); shell.capture_event(); - return; } } @@ -488,8 +483,8 @@ pub fn update<'a, Message: Clone + 'static, TopLevelMessage: Clone + 'static>( } } else { *guard = cursor.is_over(bounds); - if *guard { - if let Some(settings) = settings { + if *guard + && let Some(settings) = settings { if let Some(delay) = delay { let s = settings.clone(); let view = view.clone(); @@ -573,7 +568,6 @@ pub fn update<'a, Message: Clone + 'static, TopLevelMessage: Clone + 'static>( shell.publish((on_surface_action)(sm)); } } - } } } _ => {} diff --git a/src/widget/wrapper.rs b/src/widget/wrapper.rs index aee06e5a..b27bb9ff 100644 --- a/src/widget/wrapper.rs +++ b/src/widget/wrapper.rs @@ -1,13 +1,13 @@ -use std::borrow::Borrow; -use std::cell::RefCell; -use std::rc::Rc; -use std::thread::{self, ThreadId}; +use std::{ + borrow::Borrow, + cell::RefCell, + rc::Rc, + thread::{self, ThreadId}, +}; use crate::Element; -use iced::{Length, Rectangle, Size, event}; -use iced_core::id::Id; -use iced_core::widget::tree; -use iced_core::{Widget, widget}; +use iced::{Length, Rectangle, Size}; +use iced_core::{Widget, id::Id, widget, widget::tree}; #[derive(Debug)] pub struct RcWrapper {