diff --git a/cosmic-config/src/dbus.rs b/cosmic-config/src/dbus.rs index e689acc..e66d855 100644 --- a/cosmic-config/src/dbus.rs +++ b/cosmic-config/src/dbus.rs @@ -20,6 +20,7 @@ pub struct Watcher { impl Deref for Watcher { type Target = ConfigProxy<'static>; + #[inline] fn deref(&self) -> &Self::Target { &self.proxy } diff --git a/cosmic-config/src/lib.rs b/cosmic-config/src/lib.rs index 0c0f4db..beab95f 100644 --- a/cosmic-config/src/lib.rs +++ b/cosmic-config/src/lib.rs @@ -40,6 +40,7 @@ pub enum Error { } impl fmt::Display for Error { + #[cold] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::AtomicWrites(err) => err.fmt(f), @@ -61,6 +62,7 @@ impl Error { /// Whether the reason for the missing config is caused by an error. /// /// Useful for determining if it is appropriate to log as an error. + #[inline] pub fn is_err(&self) -> bool { !matches!(self, Self::NoConfigDirectory | Self::NotFound) } @@ -134,11 +136,6 @@ fn sanitize_name(name: &str) -> Result<&Path, Error> { } impl Config { - /// Get the config for the libcosmic toolkit - pub fn libcosmic() -> Result { - Self::new("com.system76.libcosmic", 1) - } - /// Get a system config for the given name and config version pub fn system(name: &str, version: u64) -> Result { let path = sanitize_name(name)?.join(format!("v{version}")); @@ -235,6 +232,7 @@ impl Config { } // Start a transaction (to set multiple configs at the same time) + #[inline] pub fn transaction(&self) -> ConfigTransaction { ConfigTransaction { config: self, @@ -368,7 +366,7 @@ pub struct ConfigTransaction<'a> { updates: Mutex>, } -impl<'a> ConfigTransaction<'a> { +impl ConfigTransaction<'_> { /// Apply all pending changes from ConfigTransaction //TODO: apply all changes at once pub fn commit(self) -> Result<(), Error> { @@ -386,7 +384,7 @@ impl<'a> ConfigTransaction<'a> { // Setting any setting in this way will do one transaction for all settings // when commit finishes that transaction -impl<'a> ConfigSet for ConfigTransaction<'a> { +impl ConfigSet for ConfigTransaction<'_> { fn set(&self, key: &str, value: T) -> Result<(), Error> { //TODO: sanitize key (no slashes, cannot be . or ..) let key_path = self.config.key_path(key)?; diff --git a/cosmic-config/src/subscription.rs b/cosmic-config/src/subscription.rs index 7468af0..6425595 100644 --- a/cosmic-config/src/subscription.rs +++ b/cosmic-config/src/subscription.rs @@ -16,6 +16,7 @@ pub enum ConfigUpdate { Failed, } +#[cold] pub fn config_subscription< I: 'static + Copy + Send + Sync + Hash, T: 'static + Send + Sync + PartialEq + Clone + CosmicConfigEntry, @@ -27,6 +28,7 @@ pub fn config_subscription< iced_futures::Subscription::run_with_id(id, watcher_stream(config_id, config_version, false)) } +#[cold] pub fn config_state_subscription< I: 'static + Copy + Send + Sync + Hash, T: 'static + Send + Sync + PartialEq + Clone + CosmicConfigEntry, diff --git a/cosmic-theme/src/lib.rs b/cosmic-theme/src/lib.rs index c30234b..5d59ccd 100644 --- a/cosmic-theme/src/lib.rs +++ b/cosmic-theme/src/lib.rs @@ -19,6 +19,6 @@ pub mod composite; pub mod steps; /// name of cosmic theme -pub const NAME: &'static str = "com.system76.CosmicTheme"; +pub const NAME: &str = "com.system76.CosmicTheme"; pub use palette; diff --git a/cosmic-theme/src/model/cosmic_palette.rs b/cosmic-theme/src/model/cosmic_palette.rs index 3b916c1..6a18908 100644 --- a/cosmic-theme/src/model/cosmic_palette.rs +++ b/cosmic-theme/src/model/cosmic_palette.rs @@ -26,6 +26,7 @@ pub enum CosmicPalette { impl CosmicPalette { /// extract the inner palette + #[inline] pub fn inner(self) -> CosmicPaletteInner { match self { CosmicPalette::Dark(p) => p, @@ -37,6 +38,7 @@ impl CosmicPalette { } impl AsMut for CosmicPalette { + #[inline] fn as_mut(&mut self) -> &mut CosmicPaletteInner { match self { CosmicPalette::Dark(p) => p, @@ -48,6 +50,7 @@ impl AsMut for CosmicPalette { } impl AsRef for CosmicPalette { + #[inline] fn as_ref(&self) -> &CosmicPaletteInner { match self { CosmicPalette::Dark(p) => p, @@ -60,6 +63,7 @@ impl AsRef for CosmicPalette { impl CosmicPalette { /// check if the palette is dark + #[inline] pub fn is_dark(&self) -> bool { match self { CosmicPalette::Dark(_) | CosmicPalette::HighContrastDark(_) => true, @@ -68,6 +72,7 @@ impl CosmicPalette { } /// check if the palette is high_contrast + #[inline] pub fn is_high_contrast(&self) -> bool { match self { CosmicPalette::HighContrastLight(_) | CosmicPalette::HighContrastDark(_) => true, @@ -77,6 +82,7 @@ impl CosmicPalette { } impl Default for CosmicPalette { + #[inline] fn default() -> Self { CosmicPalette::Dark(Default::default()) } @@ -164,6 +170,7 @@ pub struct CosmicPaletteInner { impl CosmicPalette { /// name of the palette + #[inline] pub fn name(&self) -> &str { match &self { CosmicPalette::Dark(p) => &p.name, diff --git a/cosmic-theme/src/model/derivation.rs b/cosmic-theme/src/model/derivation.rs index 9276142..f4147c2 100644 --- a/cosmic-theme/src/model/derivation.rs +++ b/cosmic-theme/src/model/derivation.rs @@ -77,26 +77,31 @@ pub struct Component { #[allow(clippy::must_use_candidate)] #[allow(clippy::doc_markdown)] impl Component { + #[inline] /// get @hover_state_color pub fn hover_state_color(&self) -> Srgba { self.hover } + #[inline] /// get @pressed_state_color pub fn pressed_state_color(&self) -> Srgba { self.pressed } + #[inline] /// get @selected_state_color pub fn selected_state_color(&self) -> Srgba { self.selected } + #[inline] /// get @selected_state_text_color pub fn selected_state_text_color(&self) -> Srgba { self.selected_text } + #[inline] /// get @focus_color pub fn focus_color(&self) -> Srgba { self.focus diff --git a/cosmic-theme/src/model/layout.rs b/cosmic-theme/src/model/layout.rs index 79456dc..a476b63 100644 --- a/cosmic-theme/src/model/layout.rs +++ b/cosmic-theme/src/model/layout.rs @@ -1,5 +1,4 @@ #[derive(Default)] pub struct Layout { - corner_radii: [u32;4], - -} \ No newline at end of file + corner_radii: [u32; 4], +} diff --git a/cosmic-theme/src/model/mode.rs b/cosmic-theme/src/model/mode.rs index f57c653..ce16697 100644 --- a/cosmic-theme/src/model/mode.rs +++ b/cosmic-theme/src/model/mode.rs @@ -16,6 +16,7 @@ pub struct ThemeMode { } impl Default for ThemeMode { + #[inline] fn default() -> Self { Self { is_dark: true, @@ -25,15 +26,19 @@ impl Default for ThemeMode { } impl ThemeMode { + #[inline] /// Check if the theme is currently using dark mode pub fn is_dark(config: &Config) -> Result { config.get::("is_dark") } + #[inline] + /// The current version of the theme mode config. pub const fn version() -> u64 { Self::VERSION } + #[inline] /// Get the config for the theme mode pub fn config() -> Result { Config::new(THEME_MODE_ID, Self::VERSION) diff --git a/cosmic-theme/src/model/theme.rs b/cosmic-theme/src/model/theme.rs index a36bbda..d159b40 100644 --- a/cosmic-theme/src/model/theme.rs +++ b/cosmic-theme/src/model/theme.rs @@ -103,6 +103,7 @@ pub struct Theme { } impl Default for Theme { + #[inline] fn default() -> Self { Self::preferred_theme() } @@ -121,36 +122,43 @@ impl Theme { NAME } + #[inline] /// Get the config for the current dark theme pub fn dark_config() -> Result { Config::new(DARK_THEME_ID, Self::VERSION) } + #[inline] /// Get the config for the current light theme pub fn light_config() -> Result { Config::new(LIGHT_THEME_ID, Self::VERSION) } + #[inline] /// get the built in light theme pub fn light_default() -> Self { LIGHT_PALETTE.clone().into() } + #[inline] /// get the built in dark theme pub fn dark_default() -> Self { DARK_PALETTE.clone().into() } + #[inline] /// get the built in high contrast dark theme pub fn high_contrast_dark_default() -> Self { CosmicPalette::HighContrastDark(DARK_PALETTE.as_ref().clone()).into() } + #[inline] /// get the built in high contrast light theme pub fn high_contrast_light_default() -> Self { CosmicPalette::HighContrastLight(LIGHT_PALETTE.as_ref().clone()).into() } + #[inline] /// Convert the theme to a high-contrast variant pub fn to_high_contrast(&self) -> Self { todo!(); @@ -159,6 +167,7 @@ impl Theme { // TODO convenient getter functions for each named color variable #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @accent_color pub fn accent_color(&self) -> Srgba { self.accent.base @@ -166,6 +175,7 @@ impl Theme { #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @success_color pub fn success_color(&self) -> Srgba { self.success.base @@ -173,6 +183,7 @@ impl Theme { #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @destructive_color pub fn destructive_color(&self) -> Srgba { self.destructive.base @@ -180,6 +191,7 @@ impl Theme { #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @warning_color pub fn warning_color(&self) -> Srgba { self.warning.base @@ -187,6 +199,7 @@ impl Theme { #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @small_widget_divider pub fn small_widget_divider(&self) -> Srgba { let mut neutral_9 = self.palette.neutral_9; @@ -197,42 +210,55 @@ impl Theme { // Containers #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @bg_color pub fn bg_color(&self) -> Srgba { self.background.base } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @bg_component_color pub fn bg_component_color(&self) -> Srgba { self.background.component.base } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @primary_container_color pub fn primary_container_color(&self) -> Srgba { self.primary.base } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @primary_component_color pub fn primary_component_color(&self) -> Srgba { self.primary.component.base } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @secondary_container_color pub fn secondary_container_color(&self) -> Srgba { self.secondary.base } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @secondary_component_color pub fn secondary_component_color(&self) -> Srgba { self.secondary.component.base } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @button_bg_color pub fn button_bg_color(&self) -> Srgba { self.button.base @@ -241,90 +267,119 @@ impl Theme { // Text #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @on_bg_color pub fn on_bg_color(&self) -> Srgba { self.background.on } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @on_bg_component_color pub fn on_bg_component_color(&self) -> Srgba { self.background.component.on } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @on_primary_color pub fn on_primary_container_color(&self) -> Srgba { self.primary.on } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @on_primary_component_color pub fn on_primary_component_color(&self) -> Srgba { self.primary.component.on } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @on_secondary_color pub fn on_secondary_container_color(&self) -> Srgba { self.secondary.on } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @on_secondary_component_color pub fn on_secondary_component_color(&self) -> Srgba { self.secondary.component.on } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @accent_text_color pub fn accent_text_color(&self) -> Srgba { self.accent_text.unwrap_or(self.accent.base) } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @success_text_color pub fn success_text_color(&self) -> Srgba { self.success.base } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @warning_text_color pub fn warning_text_color(&self) -> Srgba { self.warning.base } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @destructive_text_color pub fn destructive_text_color(&self) -> Srgba { self.destructive.base } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @on_accent_color pub fn on_accent_color(&self) -> Srgba { self.accent.on } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @on_success_color pub fn on_success_color(&self) -> Srgba { self.success.on } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @on_warning_color pub fn on_warning_color(&self) -> Srgba { self.warning.on } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @on_destructive_color pub fn on_destructive_color(&self) -> Srgba { self.destructive.on } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @button_color pub fn button_color(&self) -> Srgba { self.button.on @@ -333,36 +388,47 @@ impl Theme { // Borders and Dividers #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @bg_divider pub fn bg_divider(&self) -> Srgba { self.background.divider } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @bg_component_divider pub fn bg_component_divider(&self) -> Srgba { self.background.component.divider } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @primary_container_divider pub fn primary_container_divider(&self) -> Srgba { self.primary.divider } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @primary_component_divider pub fn primary_component_divider(&self) -> Srgba { self.primary.component.divider } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @secondary_container_divider pub fn secondary_container_divider(&self) -> Srgba { self.secondary.divider } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @button_divider pub fn button_divider(&self) -> Srgba { self.button.divider @@ -370,6 +436,7 @@ impl Theme { #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @window_header_bg pub fn window_header_bg(&self) -> Srgba { self.background.base @@ -377,60 +444,79 @@ impl Theme { #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @space_none pub fn space_none(&self) -> u16 { self.spacing.space_none } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @space_xxxs pub fn space_xxxs(&self) -> u16 { self.spacing.space_xxxs } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @space_xxs pub fn space_xxs(&self) -> u16 { self.spacing.space_xxs } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @space_xs pub fn space_xs(&self) -> u16 { self.spacing.space_xs } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @space_s pub fn space_s(&self) -> u16 { self.spacing.space_s } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @space_m pub fn space_m(&self) -> u16 { self.spacing.space_m } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @space_l pub fn space_l(&self) -> u16 { self.spacing.space_l } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @space_xl pub fn space_xl(&self) -> u16 { self.spacing.space_xl } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @space_xxl pub fn space_xxl(&self) -> u16 { self.spacing.space_xxl } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @space_xxxl pub fn space_xxxl(&self) -> u16 { self.spacing.space_xxxl @@ -438,36 +524,47 @@ impl Theme { #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @radius_0 pub fn radius_0(&self) -> [f32; 4] { self.corner_radii.radius_0 } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @radius_xs pub fn radius_xs(&self) -> [f32; 4] { self.corner_radii.radius_xs } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @radius_s pub fn radius_s(&self) -> [f32; 4] { self.corner_radii.radius_s } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @radius_m pub fn radius_m(&self) -> [f32; 4] { self.corner_radii.radius_m } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @radius_l pub fn radius_l(&self) -> [f32; 4] { self.corner_radii.radius_l } + #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @radius_xl pub fn radius_xl(&self) -> [f32; 4] { self.corner_radii.radius_xl @@ -475,6 +572,7 @@ impl Theme { #[must_use] #[allow(clippy::doc_markdown)] + #[inline] /// get @shade_color pub fn shade_color(&self) -> Srgba { self.shade @@ -631,6 +729,7 @@ impl Default for ThemeBuilder { } impl ThemeBuilder { + #[inline] /// Get a builder that is initialized with the default dark theme pub fn dark() -> Self { Self { @@ -639,6 +738,7 @@ impl ThemeBuilder { } } + #[inline] /// Get a builder that is initialized with the default light theme pub fn light() -> Self { Self { @@ -647,6 +747,7 @@ impl ThemeBuilder { } } + #[inline] /// Get a builder that is initialized with the default dark high contrast theme pub fn dark_high_contrast() -> Self { let palette: CosmicPalette = DARK_PALETTE.to_owned(); @@ -656,6 +757,7 @@ impl ThemeBuilder { } } + #[inline] /// Get a builder that is initialized with the default light high contrast theme pub fn light_high_contrast() -> Self { let palette: CosmicPalette = LIGHT_PALETTE.to_owned(); @@ -665,6 +767,7 @@ impl ThemeBuilder { } } + #[inline] /// Get a builder that is initialized with the provided palette pub fn palette(palette: CosmicPalette) -> Self { Self { @@ -673,60 +776,70 @@ impl ThemeBuilder { } } + #[inline] /// set the spacing of the builder pub fn spacing(mut self, spacing: Spacing) -> Self { self.spacing = spacing; self } + #[inline] /// set the corner radii of the builder pub fn corner_radii(mut self, corner_radii: CornerRadii) -> Self { self.corner_radii = corner_radii; self } + #[inline] /// apply a neutral tint to the palette pub fn neutral_tint(mut self, tint: Srgb) -> Self { self.neutral_tint = Some(tint); self } + #[inline] /// apply a text tint to the palette pub fn text_tint(mut self, tint: Srgb) -> Self { self.text_tint = Some(tint); self } + #[inline] /// apply a background color to the palette pub fn bg_color(mut self, c: Srgba) -> Self { self.bg_color = Some(c); self } + #[inline] /// apply a primary container background color to the palette pub fn primary_container_bg(mut self, c: Srgba) -> Self { self.primary_container_bg = Some(c); self } + #[inline] /// apply a accent color to the palette pub fn accent(mut self, c: Srgb) -> Self { self.accent = Some(c); self } + #[inline] /// apply a success color to the palette pub fn success(mut self, c: Srgb) -> Self { self.success = Some(c); self } + #[inline] /// apply a warning color to the palette pub fn warning(mut self, c: Srgb) -> Self { self.warning = Some(c); self } + #[inline] /// apply a destructive color to the palette pub fn destructive(mut self, c: Srgb) -> Self { self.destructive = Some(c); @@ -1139,11 +1252,13 @@ impl ThemeBuilder { theme } + #[inline] /// Get the builder for the dark config pub fn dark_config() -> Result { Config::new(DARK_THEME_BUILDER_ID, Self::VERSION) } + #[inline] /// Get the builder for the light config pub fn light_config() -> Result { Config::new(LIGHT_THEME_BUILDER_ID, Self::VERSION) diff --git a/cosmic-theme/src/output/gtk4_output.rs b/cosmic-theme/src/output/gtk4_output.rs index d0ab0c0..c172e4e 100644 --- a/cosmic-theme/src/output/gtk4_output.rs +++ b/cosmic-theme/src/output/gtk4_output.rs @@ -11,6 +11,7 @@ use super::{to_rgba, OutputError}; impl Theme { #[must_use] + #[cold] /// turn the theme into css pub fn as_gtk4(&self) -> String { let Self { @@ -145,6 +146,7 @@ impl Theme { /// # Errors /// /// Returns an `OutputError` if there is an error writing the CSS file. + #[cold] pub fn write_gtk4(&self) -> Result<(), OutputError> { let css_str = self.as_gtk4(); let Some(config_dir) = dirs::config_dir() else { @@ -174,6 +176,7 @@ impl Theme { /// # Errors /// /// Returns an `OutputError` if there is an error applying the CSS file. + #[cold] pub fn apply_gtk(is_dark: bool) -> Result<(), OutputError> { let Some(config_dir) = dirs::config_dir() else { return Err(OutputError::MissingConfigDir); @@ -213,6 +216,7 @@ impl Theme { /// # Errors /// /// Returns an `OutputError` if there is an error resetting the CSS file. + #[cold] pub fn reset_gtk() -> Result<(), OutputError> { let Some(config_dir) = dirs::config_dir() else { return Err(OutputError::MissingConfigDir); @@ -229,6 +233,7 @@ impl Theme { res } + #[cold] fn backup_non_cosmic_css(path: &Path, cosmic_css: &Path) -> io::Result<()> { if !Self::is_cosmic_css(path, cosmic_css)?.unwrap_or(true) { let backup_path = path.with_extension("css.bak"); @@ -237,6 +242,7 @@ impl Theme { Ok(()) } + #[cold] fn reset_cosmic_css(path: &Path, cosmic_css: &Path) -> io::Result<()> { if Self::is_cosmic_css(path, cosmic_css)?.unwrap_or_default() { fs::remove_file(path)?; diff --git a/cosmic-theme/src/output/mod.rs b/cosmic-theme/src/output/mod.rs index f282233..f2eb6b4 100644 --- a/cosmic-theme/src/output/mod.rs +++ b/cosmic-theme/src/output/mod.rs @@ -19,6 +19,7 @@ pub enum OutputError { } impl Theme { + #[inline] pub fn apply_exports(&self) -> Result<(), OutputError> { let gtk_res = Theme::apply_gtk(self.is_dark); let vs_res = self.clone().apply_vs_code(); @@ -27,12 +28,14 @@ impl Theme { Ok(()) } + #[inline] pub fn write_exports(&self) -> Result<(), OutputError> { let gtk_res = self.write_gtk4(); gtk_res?; Ok(()) } + #[inline] pub fn reset_exports() -> Result<(), OutputError> { let gtk_res = Theme::reset_gtk(); let vs_res = Theme::reset_vs_code(); diff --git a/cosmic-theme/src/output/vs_code.rs b/cosmic-theme/src/output/vs_code.rs index 11403db..5c770cd 100644 --- a/cosmic-theme/src/output/vs_code.rs +++ b/cosmic-theme/src/output/vs_code.rs @@ -266,6 +266,7 @@ impl From for VsTheme { } impl Theme { + #[cold] pub fn apply_vs_code(self) -> Result<(), OutputError> { let vs_theme = VsTheme::from(self); let config_dir = dirs::config_dir().ok_or(OutputError::MissingConfigDir)?; @@ -289,6 +290,7 @@ impl Theme { Ok(()) } + #[cold] pub fn reset_vs_code() -> Result<(), OutputError> { let config_dir = dirs::config_dir().ok_or(OutputError::MissingConfigDir)?; let vs_code_dir = config_dir.join("Code").join("User"); diff --git a/src/app/cosmic.rs b/src/app/cosmic.rs index 919e604..ec129d3 100644 --- a/src/app/cosmic.rs +++ b/src/app/cosmic.rs @@ -6,16 +6,16 @@ use std::collections::HashMap; use std::sync::Arc; use super::{Action, Application, ApplicationExt, Subscription}; -use crate::theme::{Theme, ThemeType, THEME}; -use crate::{keyboard_nav, Core, Element}; +use crate::theme::{THEME, Theme, ThemeType}; +use crate::{Core, Element, keyboard_nav}; #[cfg(feature = "wayland")] use cctk::sctk::reexports::csd_frame::{WindowManagerCapabilities, WindowState}; use cosmic_theme::ThemeMode; -#[cfg(feature = "wayland")] -use iced::event::wayland; #[cfg(not(any(feature = "multi-window", feature = "wayland")))] use iced::Application as IcedApplication; -use iced::{window, Task}; +#[cfg(feature = "wayland")] +use iced::event::wayland; +use iced::{Task, window}; use iced_futures::event::listen_with; use palette::color_difference::EuclideanDistance; @@ -243,6 +243,7 @@ where } #[allow(clippy::too_many_lines)] + #[cold] pub fn subscription(&self) -> Subscription> { let window_events = listen_with(|event, _, id| { match event { @@ -410,6 +411,7 @@ where impl Cosmic { #[allow(clippy::unused_self)] + #[cold] pub fn close(&mut self) -> iced::Task> { if let Some(id) = self.app.core().main_window_id() { iced::window::close(id) @@ -490,10 +492,10 @@ impl Cosmic { Action::KeyboardNav(message) => match message { keyboard_nav::Action::FocusNext => { - return iced::widget::focus_next().map(crate::Action::Cosmic) + return iced::widget::focus_next().map(crate::Action::Cosmic); } keyboard_nav::Action::FocusPrevious => { - return iced::widget::focus_previous().map(crate::Action::Cosmic) + return iced::widget::focus_previous().map(crate::Action::Cosmic); } keyboard_nav::Action::Escape => return self.app.on_escape(), keyboard_nav::Action::Search => return self.app.on_search(), diff --git a/src/app/mod.rs b/src/app/mod.rs index 4af3f34..2f4192b 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -17,10 +17,10 @@ pub mod settings; pub type Task = iced::Task>; +pub use crate::Core; use crate::prelude::*; use crate::theme::THEME; use crate::widget::{container, horizontal_space, id_container, menu, nav_bar, popover}; -pub use crate::Core; use apply::Apply; use context_drawer::ContextDrawer; use iced::window; @@ -28,6 +28,7 @@ use iced::{Length, Subscription}; pub use settings::Settings; use std::borrow::Cow; +#[cold] pub(crate) fn iced_settings( settings: Settings, flags: App::Flags, @@ -681,11 +682,10 @@ impl ApplicationExt for App { }; // Ensures visually aligned radii for content and window corners - let window_corner_radius = - crate::theme::active() - .cosmic() - .radius_s() - .map(|x| if x < 4.0 { x } else { x + 4.0 }); + let window_corner_radius = crate::theme::active() + .cosmic() + .radius_s() + .map(|x| if x < 4.0 { x } else { x + 4.0 }); let view_column = crate::widget::column::with_capacity(2) .push_maybe(if core.window.show_headerbar { @@ -811,6 +811,7 @@ const EMBEDDED_FONTS: &[&[u8]] = &[ include_bytes!("../../res/noto/NotoSansMono-Bold.ttf"), ]; +#[cold] fn preload_fonts() { let mut font_system = iced::advanced::graphics::text::font_system() .write() diff --git a/src/config/mod.rs b/src/config/mod.rs index 1e82bec..dedadbc 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -134,6 +134,7 @@ impl Default for CosmicTk { } impl CosmicTk { + #[inline] pub fn config() -> Result { Config::new(ID, Self::VERSION) } diff --git a/src/core.rs b/src/core.rs index fdeeba5..744b33b 100644 --- a/src/core.rs +++ b/src/core.rs @@ -6,7 +6,7 @@ use std::collections::HashMap; use crate::widget::nav_bar; use cosmic_config::CosmicConfigEntry; use cosmic_theme::ThemeMode; -use iced::{window, Limits, Size}; +use iced::{Limits, Size, window}; use iced_core::window::Id; use palette::Srgba; use slotmap::Key; @@ -161,45 +161,52 @@ impl Default for Core { impl Core { /// Whether the window is too small for the nav bar + main content. #[must_use] - pub fn is_condensed(&self) -> bool { + #[inline] + pub const fn is_condensed(&self) -> bool { self.is_condensed } /// The scaling factor used by the application. #[must_use] - pub fn scale_factor(&self) -> f32 { + #[inline] + pub const fn scale_factor(&self) -> f32 { self.scale_factor } /// Enable or disable keyboard navigation - pub fn set_keyboard_nav(&mut self, enabled: bool) { + #[inline] + pub const fn set_keyboard_nav(&mut self, enabled: bool) { self.keyboard_nav = enabled; } - #[must_use] /// Enable or disable keyboard navigation - pub fn keyboard_nav(&self) -> bool { + #[must_use] + #[inline] + pub const fn keyboard_nav(&self) -> bool { self.keyboard_nav } /// Changes the scaling factor used by the application. + #[cold] pub(crate) fn set_scale_factor(&mut self, factor: f32) { self.scale_factor = factor; self.is_condensed_update(); } /// Set header bar title + #[inline] pub fn set_header_title(&mut self, title: String) { self.window.header_title = title; } + #[inline] /// Whether to show or hide the main window's content. pub(crate) fn show_content(&self) -> bool { !self.is_condensed || !self.nav_bar.toggled_condensed } - /// Call this whenever the scaling factor or window width has changed. #[allow(clippy::cast_precision_loss)] + /// Call this whenever the scaling factor or window width has changed. fn is_condensed_update(&mut self) { // Nav bar (280px) + padding (8px) + content (360px) let mut breakpoint = 280.0 + 8.0 + 360.0; @@ -212,6 +219,7 @@ impl Core { self.nav_bar_update(); } + #[inline] fn condensed_conflict(&self) -> bool { // There is a conflict if the view is condensed and both the nav bar and context drawer are open on the same layer self.is_condensed @@ -220,6 +228,7 @@ impl Core { && !self.window.context_is_overlay } + #[inline] pub(crate) fn context_width(&self, has_nav: bool) -> f32 { let window_width = self.window.width / self.scale_factor; @@ -230,12 +239,14 @@ impl Core { reserved_width += 280.0 + 8.0; } + #[allow(clippy::manual_clamp)] // This logic is to ensure the context drawer does not take up too much of the content's space // The minimum width is 344px and the maximum with is 480px // We want to keep the content at least 360px until going down to the minimum width (window_width - reserved_width).min(480.0).max(344.0) } + #[cold] pub fn set_show_context(&mut self, show: bool) { self.window.show_context = show; self.is_condensed_update(); @@ -246,38 +257,46 @@ impl Core { } } + #[inline] pub fn main_window_is(&self, id: iced::window::Id) -> bool { self.main_window_id().is_some_and(|main_id| main_id == id) } /// Whether the nav panel is visible or not #[must_use] - pub fn nav_bar_active(&self) -> bool { + #[inline] + pub const fn nav_bar_active(&self) -> bool { self.nav_bar.active } + #[inline] pub fn nav_bar_toggle(&mut self) { self.nav_bar.toggled = !self.nav_bar.toggled; self.nav_bar_set_toggled_condensed(self.nav_bar.toggled); } + #[inline] pub fn nav_bar_toggle_condensed(&mut self) { self.nav_bar_set_toggled_condensed(!self.nav_bar.toggled_condensed); } - pub(crate) fn nav_bar_context(&self) -> nav_bar::Id { + #[inline] + pub(crate) const fn nav_bar_context(&self) -> nav_bar::Id { self.nav_bar.context_id } + #[inline] pub(crate) fn nav_bar_set_context(&mut self, id: nav_bar::Id) { self.nav_bar.context_id = id; } + #[inline] pub fn nav_bar_set_toggled(&mut self, toggled: bool) { self.nav_bar.toggled = toggled; self.nav_bar_set_toggled_condensed(self.nav_bar.toggled); } + #[cold] pub(crate) fn nav_bar_set_toggled_condensed(&mut self, toggled: bool) { self.nav_bar.toggled_condensed = toggled; self.nav_bar_update(); @@ -293,6 +312,7 @@ impl Core { } } + #[inline] pub(crate) fn nav_bar_update(&mut self) { self.nav_bar.active = if self.is_condensed { self.nav_bar.toggled_condensed @@ -301,25 +321,29 @@ impl Core { }; } + #[inline] /// Set the height of the main window. - pub(crate) fn set_window_height(&mut self, new_height: f32) { + pub(crate) const fn set_window_height(&mut self, new_height: f32) { self.window.height = new_height; } + #[inline] /// Set the width of the main window. pub(crate) fn set_window_width(&mut self, new_width: f32) { self.window.width = new_width; self.is_condensed_update(); } + #[inline] /// Get the current system theme - pub fn system_theme(&self) -> &Theme { + pub const fn system_theme(&self) -> &Theme { &self.system_theme } + #[inline] #[must_use] /// Get the current system theme mode - pub fn system_theme_mode(&self) -> ThemeMode { + pub const fn system_theme_mode(&self) -> ThemeMode { self.system_theme_mode } @@ -359,12 +383,14 @@ impl Core { /// Get the current focused window if it exists #[must_use] - pub fn focused_window(&self) -> Option { + #[inline] + pub const fn focused_window(&self) -> Option { self.focused_window } /// Whether the application should use a dark theme, according to the system #[must_use] + #[inline] pub fn system_is_dark(&self) -> bool { self.portal_is_dark .unwrap_or(self.system_theme_mode.is_dark) @@ -372,11 +398,13 @@ impl Core { /// The [`Id`] of the main window #[must_use] + #[inline] pub fn main_window_id(&self) -> Option { self.main_window.filter(|id| iced::window::Id::NONE != *id) } /// Reset the tracked main window to a new value + #[inline] pub fn set_main_window_id(&mut self, mut id: Option) -> Option { std::mem::swap(&mut self.main_window, &mut id); id diff --git a/src/dbus_activation.rs b/src/dbus_activation.rs index 84b5d00..4fffa42 100644 --- a/src/dbus_activation.rs +++ b/src/dbus_activation.rs @@ -5,14 +5,15 @@ use { crate::ApplicationExt, iced::Subscription, iced_futures::futures::{ - channel::mpsc::{Receiver, Sender}, SinkExt, + channel::mpsc::{Receiver, Sender}, }, std::{any::TypeId, collections::HashMap}, url::Url, zbus::{interface, proxy, zvariant::Value}, }; +#[cold] pub fn subscription() -> Subscription> { use iced_futures::futures::StreamExt; iced_futures::Subscription::run_with_id( @@ -105,10 +106,12 @@ pub struct DbusActivation(Option>); impl DbusActivation { #[must_use] + #[inline] pub fn new() -> Self { Self(None) } + #[inline] pub fn rx(&mut self) -> Receiver { let (tx, rx) = iced_futures::futures::channel::mpsc::channel(10); self.0 = Some(tx); @@ -139,6 +142,7 @@ pub trait DbusActivationInterface { #[interface(name = "org.freedesktop.DbusActivation")] impl DbusActivation { + #[cold] async fn activate(&mut self, platform_data: HashMap<&str, Value<'_>>) { if let Some(tx) = &mut self.0 { let _ = tx @@ -159,6 +163,7 @@ impl DbusActivation { } } + #[cold] async fn open(&mut self, uris: Vec<&str>, platform_data: HashMap<&str, Value<'_>>) { if let Some(tx) = &mut self.0 { let _ = tx @@ -181,6 +186,7 @@ impl DbusActivation { } } + #[cold] async fn activate_action( &mut self, action_name: &str, diff --git a/src/desktop.rs b/src/desktop.rs index 3f5f575..ee35887 100644 --- a/src/desktop.rs +++ b/src/desktop.rs @@ -240,6 +240,7 @@ impl DesktopEntryData { } #[cfg(not(windows))] +#[cold] pub async fn spawn_desktop_exec(exec: S, env_vars: I, app_id: Option<&str>) where S: AsRef, diff --git a/src/font.rs b/src/font.rs index c390cb6..e0eb474 100644 --- a/src/font.rs +++ b/src/font.rs @@ -6,10 +6,12 @@ pub use iced::Font; use iced_core::font::Weight; +#[inline] pub fn default() -> Font { Font::from(crate::config::interface_font()) } +#[inline] pub fn light() -> Font { Font { weight: Weight::Light, @@ -17,6 +19,7 @@ pub fn light() -> Font { } } +#[inline] pub fn semibold() -> Font { Font { weight: Weight::Semibold, @@ -24,6 +27,7 @@ pub fn semibold() -> Font { } } +#[inline] pub fn bold() -> Font { Font { weight: Weight::Bold, @@ -31,6 +35,7 @@ pub fn bold() -> Font { } } +#[inline] pub fn mono() -> Font { Font::from(crate::config::monospace_font()) } diff --git a/src/icon_theme.rs b/src/icon_theme.rs index 277d2cf..69fe584 100644 --- a/src/icon_theme.rs +++ b/src/icon_theme.rs @@ -13,12 +13,14 @@ pub(crate) static DEFAULT: Mutex> = Mutex::new(Cow::Borrowed(C /// The fallback icon theme to search if no icon theme was specified. #[must_use] #[allow(clippy::missing_panics_doc)] +#[inline] pub fn default() -> String { DEFAULT.lock().unwrap().to_string() } /// Set the fallback icon theme to search when loading system icons. #[allow(clippy::missing_panics_doc)] +#[cold] pub fn set_default(name: impl Into>) { *DEFAULT.lock().unwrap() = name.into(); } diff --git a/src/keyboard_nav.rs b/src/keyboard_nav.rs index 6521146..961a423 100644 --- a/src/keyboard_nav.rs +++ b/src/keyboard_nav.rs @@ -3,7 +3,7 @@ //! Subscribe to common application keyboard shortcuts. -use iced::{event, keyboard, Event, Subscription}; +use iced::{Event, Subscription, event, keyboard}; use iced_core::keyboard::key::Named; use iced_futures::event::listen_raw; @@ -16,6 +16,7 @@ pub enum Action { Search, } +#[cold] pub fn subscription() -> Subscription { listen_raw(|event, status, _| { if event::Status::Ignored != status { diff --git a/src/malloc.rs b/src/malloc.rs index a56323f..b99a66f 100644 --- a/src/malloc.rs +++ b/src/malloc.rs @@ -11,6 +11,7 @@ unsafe extern "C" { fn mallopt(param: c_int, value: c_int) -> c_int; } +#[inline] pub fn trim(pad: usize) { unsafe { malloc_trim(pad); @@ -18,6 +19,7 @@ pub fn trim(pad: usize) { } /// Prevents glibc from hoarding memory via memory fragmentation. +#[inline] pub fn limit_mmap_threshold(threshold: i32) { unsafe { mallopt(M_MMAP_THRESHOLD, threshold as c_int); diff --git a/src/process.rs b/src/process.rs index b1a3ae0..1ad048d 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::{exit, Command, Stdio}; +use std::process::{Command, Stdio, exit}; #[cfg(feature = "tokio")] use tokio::io::AsyncReadExt; @@ -24,6 +24,7 @@ async fn read_from_pipe(read: OwnedFd) -> Option { } /// Performs a double fork with setsid to spawn and detach a command. +#[cold] pub async fn spawn(mut command: Command) -> Option { // NOTE: Windows platform is not supported command diff --git a/src/surface/mod.rs b/src/surface/mod.rs index c08108e..3041fa5 100644 --- a/src/surface/mod.rs +++ b/src/surface/mod.rs @@ -50,6 +50,7 @@ pub enum Action { } impl std::fmt::Debug for Action { + #[cold] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::AppSubsurface(arg0, arg1) => f diff --git a/src/theme/mod.rs b/src/theme/mod.rs index f2e4203..e0b0a42 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -53,36 +53,41 @@ pub(crate) static THEME: Mutex = Mutex::new(Theme { }); /// Currently-defined theme. +#[inline] #[allow(clippy::missing_panics_doc)] pub fn active() -> Theme { THEME.lock().unwrap().clone() } /// Currently-defined theme type. +#[inline] #[allow(clippy::missing_panics_doc)] pub fn active_type() -> ThemeType { THEME.lock().unwrap().theme_type.clone() } /// Preferred interface spacing parameters defined by the active theme. -#[inline(always)] +#[inline] pub fn spacing() -> Spacing { active().cosmic().spacing } /// Whether the active theme has a dark preference. +#[inline] #[must_use] pub fn is_dark() -> bool { active_type().is_dark() } /// Whether the active theme is high contrast. +#[inline] #[must_use] pub fn is_high_contrast() -> bool { active_type().is_high_contrast() } /// Watches for changes to the system's theme preference. +#[cold] pub fn subscription(is_dark: bool) -> Subscription { config_subscription::<_, crate::cosmic_theme::Theme>( ( @@ -173,6 +178,7 @@ pub enum ThemeType { impl ThemeType { /// Whether the theme has a dark preference. #[must_use] + #[inline] pub fn is_dark(&self) -> bool { match self { Self::Dark | Self::HighContrastDark => true, @@ -182,6 +188,7 @@ impl ThemeType { } /// Whether the theme has a high contrast. + #[inline] #[must_use] pub fn is_high_contrast(&self) -> bool { match self { @@ -191,6 +198,7 @@ impl ThemeType { } } + #[inline] /// Prefer dark or light theme. /// If `None`, the system preference is used. pub fn prefer_dark(&mut self, new_prefer_dark: Option) { @@ -208,6 +216,7 @@ pub struct Theme { } impl Theme { + #[inline] pub fn cosmic(&self) -> &cosmic_theme::Theme { match self.theme_type { ThemeType::Dark => &COSMIC_DARK, @@ -218,6 +227,7 @@ impl Theme { } } + #[inline] pub fn dark() -> Self { Self { theme_type: ThemeType::Dark, @@ -225,6 +235,7 @@ impl Theme { } } + #[inline] pub fn light() -> Self { Self { theme_type: ThemeType::Light, @@ -232,6 +243,7 @@ impl Theme { } } + #[inline] pub fn dark_hc() -> Self { Self { theme_type: ThemeType::HighContrastDark, @@ -239,6 +251,7 @@ impl Theme { } } + #[inline] pub fn light_hc() -> Self { Self { theme_type: ThemeType::HighContrastLight, @@ -246,6 +259,7 @@ impl Theme { } } + #[inline] pub fn custom(theme: Arc) -> Self { Self { theme_type: ThemeType::Custom(theme), @@ -253,6 +267,7 @@ impl Theme { } } + #[inline] pub fn system(theme: Arc) -> Self { Self { theme_type: ThemeType::System { @@ -263,6 +278,7 @@ impl Theme { } } + #[inline] /// get current container /// can be used in a component that is intended to be a child of a `CosmicContainer` pub fn current_container(&self) -> &cosmic_theme::Container { @@ -273,6 +289,7 @@ impl Theme { } } + #[inline] /// set the theme pub fn set_theme(&mut self, theme: ThemeType) { self.theme_type = theme; @@ -280,6 +297,7 @@ impl Theme { } impl LayeredTheme for Theme { + #[inline] fn set_layer(&mut self, layer: cosmic_theme::Layer) { self.layer = layer; } diff --git a/src/theme/portal.rs b/src/theme/portal.rs index e3dc751..f0c88c0 100644 --- a/src/theme/portal.rs +++ b/src/theme/portal.rs @@ -1,6 +1,6 @@ -use ashpd::desktop::settings::{ColorScheme, Contrast}; use ashpd::desktop::Color; -use iced::futures::{self, select, FutureExt, SinkExt, StreamExt}; +use ashpd::desktop::settings::{ColorScheme, Contrast}; +use iced::futures::{self, FutureExt, SinkExt, StreamExt, select}; use iced_futures::stream; use tracing::error; @@ -11,6 +11,7 @@ pub enum Desktop { Contrast(Contrast), } +#[cold] pub fn desktop_settings() -> iced_futures::Subscription { iced_futures::Subscription::run_with_id( std::any::TypeId::of::(), diff --git a/src/widget/aspect_ratio.rs b/src/widget/aspect_ratio.rs index 39ac9c5..e66c14d 100644 --- a/src/widget/aspect_ratio.rs +++ b/src/widget/aspect_ratio.rs @@ -1,7 +1,7 @@ //! A container which constraints itself to a specific aspect ratio. -use iced::widget::Container; use iced::Size; +use iced::widget::Container; use iced_core::event::{self, Event}; use iced_core::layout; use iced_core::mouse; @@ -76,6 +76,7 @@ where /// Sets the width of the [`self.`]. #[must_use] + #[inline] pub fn width(mut self, width: Length) -> Self { self.container = self.container.width(width); self @@ -83,6 +84,7 @@ where /// Sets the height of the [`Container`]. #[must_use] + #[inline] pub fn height(mut self, height: Length) -> Self { self.container = self.container.height(height); self @@ -90,6 +92,7 @@ where /// Sets the maximum width of the [`Container`]. #[must_use] + #[inline] pub fn max_width(mut self, max_width: f32) -> Self { self.container = self.container.max_width(max_width); self @@ -97,6 +100,7 @@ where /// Sets the maximum height of the [`Container`] in pixels. #[must_use] + #[inline] pub fn max_height(mut self, max_height: f32) -> Self { self.container = self.container.max_height(max_height); self @@ -104,6 +108,7 @@ where /// Sets the content alignment for the horizontal axis of the [`Container`]. #[must_use] + #[inline] pub fn align_x(mut self, alignment: Alignment) -> Self { self.container = self.container.align_x(alignment); self @@ -111,6 +116,7 @@ where /// Sets the content alignment for the vertical axis of the [`Container`]. #[must_use] + #[inline] pub fn align_y(mut self, alignment: Alignment) -> Self { self.container = self.container.align_y(alignment); self @@ -118,6 +124,7 @@ where /// Centers the contents in the horizontal axis of the [`Container`]. #[must_use] + #[inline] pub fn center_x(mut self, width: Length) -> Self { self.container = self.container.center_x(width); self @@ -125,6 +132,7 @@ where /// Centers the contents in the vertical axis of the [`Container`]. #[must_use] + #[inline] pub fn center_y(mut self, height: Length) -> Self { self.container = self.container.center_y(height); self @@ -132,6 +140,7 @@ where /// Centers the contents in the horizontal and vertical axis of the [`Container`]. #[must_use] + #[inline] pub fn center(mut self, length: Length) -> Self { self.container = self.container.center(length); self diff --git a/src/widget/autosize.rs b/src/widget/autosize.rs index 3f60835..172d505 100644 --- a/src/widget/autosize.rs +++ b/src/widget/autosize.rs @@ -54,36 +54,43 @@ where } } + #[inline] pub fn limits(mut self, limits: layout::Limits) -> Self { self.limits = limits; self } + #[inline] pub fn auto_width(mut self, auto_width: bool) -> Self { self.auto_width = auto_width; self } + #[inline] pub fn auto_height(mut self, auto_height: bool) -> Self { self.auto_height = auto_height; self } + #[inline] pub fn max_width(mut self, v: f32) -> Self { self.limits = self.limits.max_width(v); self } + #[inline] pub fn max_height(mut self, v: f32) -> Self { self.limits = self.limits.max_height(v); self } + #[inline] pub fn min_width(mut self, v: f32) -> Self { self.limits = self.limits.min_width(v); self } + #[inline] pub fn min_height(mut self, v: f32) -> Self { self.limits = self.limits.min_height(v); self diff --git a/src/widget/button/icon.rs b/src/widget/button/icon.rs index 3b46d9d..0bb3c84 100644 --- a/src/widget/button/icon.rs +++ b/src/widget/button/icon.rs @@ -2,13 +2,13 @@ // SPDX-License-Identifier: MPL-2.0 use super::{Builder, ButtonClass}; +use crate::Element; use crate::widget::{ icon::{self, Handle}, tooltip, }; -use crate::Element; use apply::Apply; -use iced_core::{font::Weight, text::LineHeight, widget::Id, 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>; @@ -114,11 +114,13 @@ impl Button<'_, Message> { self } + #[inline] pub fn selected(mut self, selected: bool) -> Self { self.variant.selected = selected; self } + #[inline] pub fn vertical(mut self, vertical: bool) -> Self { self.variant.vertical = vertical; self.class = ButtonClass::IconVertical; diff --git a/src/widget/button/image.rs b/src/widget/button/image.rs index 74e3b37..6a5c47b 100644 --- a/src/widget/button/image.rs +++ b/src/widget/button/image.rs @@ -3,10 +3,10 @@ use super::Builder; use crate::{ - widget::{self, image::Handle}, Element, + widget::{self, image::Handle}, }; -use iced_core::{font::Weight, widget::Id, Length, Padding}; +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>>; @@ -28,6 +28,7 @@ pub struct Image<'a, Handle, Message> { } impl<'a, Message> Button<'a, Message> { + #[inline] pub fn new(variant: Image<'a, Handle, Message>) -> Self { Self { id: Id::unique(), @@ -47,16 +48,19 @@ impl<'a, Message> Button<'a, Message> { } } + #[inline] pub fn on_remove(mut self, message: Message) -> Self { self.variant.on_remove = Some(message); self } + #[inline] pub fn on_remove_maybe(mut self, message: Option) -> Self { self.variant.on_remove = message; self } + #[inline] pub fn selected(mut self, selected: bool) -> Self { self.variant.selected = selected; self diff --git a/src/widget/button/link.rs b/src/widget/button/link.rs index 77527ec..dcfc6a3 100644 --- a/src/widget/button/link.rs +++ b/src/widget/button/link.rs @@ -55,6 +55,7 @@ impl<'a, Message> Button<'a, Message> { } } +#[inline(never)] pub fn icon() -> Handle { icon::from_svg_bytes(&include_bytes!("external-link.svg")[..]).symbolic(true) } diff --git a/src/widget/button/mod.rs b/src/widget/button/mod.rs index 9928628..b654b27 100644 --- a/src/widget/button/mod.rs +++ b/src/widget/button/mod.rs @@ -45,7 +45,7 @@ use std::borrow::Cow; /// A button with a custom element for its content. pub fn custom<'a, Message>(content: impl Into>) -> Button<'a, Message> { - Button::new(content) + Button::new(content.into()) } /// An image button which may contain any widget as its content. @@ -53,7 +53,7 @@ pub fn custom_image_button<'a, Message>( content: impl Into>, on_remove: Option, ) -> Button<'a, Message> { - Button::new_image(content, on_remove) + Button::new_image(content.into(), on_remove) } /// A builder for constructing a custom [`Button`]. diff --git a/src/widget/button/text.rs b/src/widget/button/text.rs index 1b68239..da5f94f 100644 --- a/src/widget/button/text.rs +++ b/src/widget/button/text.rs @@ -3,8 +3,7 @@ use super::{Builder, ButtonClass}; use crate::widget::{icon, row, tooltip}; -use crate::{ext::CollectionWidget, Element}; -use apply::Apply; +use crate::{Apply, Element}; use iced_core::{font::Weight, text::LineHeight, widget::Id, Alignment, Length, Padding}; use std::borrow::Cow; diff --git a/src/widget/button/widget.rs b/src/widget/button/widget.rs index 3b6d557..3a1df24 100644 --- a/src/widget/button/widget.rs +++ b/src/widget/button/widget.rs @@ -7,19 +7,19 @@ //! A [`Button`] has some local [`State`]. use iced_runtime::core::widget::Id; -use iced_runtime::{keyboard, task, Action, Task}; +use iced_runtime::{Action, Task, keyboard, task}; use iced_core::event::{self, Event}; use iced_core::renderer::{self, Quad, Renderer}; use iced_core::touch; -use iced_core::widget::tree::{self, Tree}; use iced_core::widget::Operation; -use iced_core::{layout, svg}; -use iced_core::{mouse, Border}; -use iced_core::{overlay, Shadow}; +use iced_core::widget::tree::{self, Tree}; use iced_core::{ 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; @@ -118,24 +118,28 @@ impl<'a, Message> Button<'a, Message> { } /// Sets the [`Id`] of the [`Button`]. + #[inline] pub fn id(mut self, id: Id) -> Self { self.id = id; self } /// Sets the width of the [`Button`]. + #[inline] pub fn width(mut self, width: impl Into) -> Self { self.width = width.into(); self } /// Sets the height of the [`Button`]. + #[inline] pub fn height(mut self, height: impl Into) -> Self { self.height = height.into(); self } /// Sets the [`Padding`] of the [`Button`]. + #[inline] pub fn padding>(mut self, padding: P) -> Self { self.padding = padding.into(); self @@ -144,6 +148,7 @@ impl<'a, Message> Button<'a, Message> { /// Sets the message that will be produced when the [`Button`] is pressed and released. /// /// Unless `on_press` or `on_press_down` is called, the [`Button`] will be disabled. + #[inline] pub fn on_press(mut self, on_press: Message) -> Self { self.on_press = Some(on_press); self @@ -152,6 +157,7 @@ impl<'a, Message> Button<'a, Message> { /// Sets the message that will be produced when the [`Button`] is pressed, /// /// Unless `on_press` or `on_press_down` is called, the [`Button`] will be disabled. + #[inline] pub fn on_press_down(mut self, on_press: Message) -> Self { self.on_press_down = Some(on_press); self @@ -161,12 +167,14 @@ impl<'a, Message> Button<'a, Message> { /// if `Some`. /// /// If `None`, the [`Button`] will be disabled. + #[inline] pub fn on_press_maybe(mut self, on_press: Option) -> Self { self.on_press = on_press; self } /// Sets the the [`Button`] to enabled whether or not it has handlers for on press. + #[inline] pub fn force_enabled(mut self, enabled: bool) -> Self { self.force_enabled = enabled; self @@ -175,6 +183,7 @@ impl<'a, Message> Button<'a, Message> { /// Sets the widget to a selected state. /// /// Displays a selection indicator on image buttons. + #[inline] pub fn selected(mut self, selected: bool) -> Self { self.selected = selected; @@ -182,6 +191,7 @@ impl<'a, Message> Button<'a, Message> { } /// Sets the style variant of this [`Button`]. + #[inline] pub fn class(mut self, style: crate::theme::Button) -> Self { self.style = style; self @@ -579,8 +589,8 @@ impl<'a, Message: 'a + Clone> Widget p: mouse::Cursor, ) -> iced_accessibility::A11yTree { use iced_accessibility::{ - accesskit::{Action, DefaultActionVerb, NodeBuilder, NodeId, Rect, Role}, A11yNode, A11yTree, + accesskit::{Action, DefaultActionVerb, NodeBuilder, NodeId, Rect, Role}, }; // TODO why is state None sometimes? if matches!(state.state, iced_core::widget::tree::State::None) { @@ -668,26 +678,31 @@ pub struct State { impl State { /// Creates a new [`State`]. + #[inline] pub fn new() -> Self { Self::default() } /// Returns whether the [`Button`] is currently focused or not. + #[inline] pub fn is_focused(self) -> bool { self.is_focused } /// Returns whether the [`Button`] is currently hovered or not. + #[inline] pub fn is_hovered(self) -> bool { self.is_hovered } /// Focuses the [`Button`]. + #[inline] pub fn focus(&mut self) { self.is_focused = true; } /// Unfocuses the [`Button`]. + #[inline] pub fn unfocus(&mut self) { self.is_focused = false; } @@ -951,14 +966,17 @@ pub fn focus(id: Id) -> Task { } impl operation::Focusable for State { + #[inline] fn is_focused(&self) -> bool { Self::is_focused(*self) } + #[inline] fn focus(&mut self) { Self::focus(self); } + #[inline] fn unfocus(&mut self) { Self::unfocus(self); } diff --git a/src/widget/calendar.rs b/src/widget/calendar.rs index ea96360..046a95d 100644 --- a/src/widget/calendar.rs +++ b/src/widget/calendar.rs @@ -6,7 +6,7 @@ use std::cmp; use crate::iced_core::{Alignment, Length, Padding}; -use crate::widget::{button, column, grid, icon, row, text, Grid}; +use crate::widget::{Grid, button, column, grid, icon, row, text}; use chrono::{Datelike, Days, Local, Months, NaiveDate, Weekday}; /// A widget that displays an interactive calendar. @@ -58,6 +58,7 @@ impl CalendarModel { } } + #[inline] pub fn new(selected: NaiveDate, visible: NaiveDate) -> Self { CalendarModel { selected, visible } } @@ -80,16 +81,19 @@ impl CalendarModel { self.visible = next_month_date; } + #[inline] pub fn set_prev_month(&mut self) { self.show_prev_month(); self.selected = self.visible; } + #[inline] pub fn set_next_month(&mut self) { self.show_next_month(); self.selected = self.visible; } + #[inline] pub fn set_selected_visible(&mut self, selected: NaiveDate) { self.selected = selected; self.visible = self.selected; @@ -225,6 +229,7 @@ fn padded_control<'a, Message>( .width(Length::Fill) } +#[inline] fn menu_control_padding() -> Padding { let guard = crate::theme::THEME.lock().unwrap(); let cosmic = guard.cosmic(); diff --git a/src/widget/context_drawer/widget.rs b/src/widget/context_drawer/widget.rs index c59ae40..f36578e 100644 --- a/src/widget/context_drawer/widget.rs +++ b/src/widget/context_drawer/widget.rs @@ -3,17 +3,17 @@ use std::borrow::Cow; -use crate::widget::{button, column, container, icon, row, scrollable, text, LayerContainer}; +use crate::widget::{LayerContainer, button, column, container, icon, row, scrollable, text}; use crate::{Apply, Element, Renderer, Theme}; use super::overlay::Overlay; +use iced_core::Alignment; use iced_core::event::{self, Event}; use iced_core::widget::{Operation, Tree}; -use iced_core::Alignment; use iced_core::{ - layout, mouse, overlay as iced_overlay, renderer, Clipboard, Layout, Length, Rectangle, Shell, - Vector, Widget, + Clipboard, Layout, Length, Rectangle, Shell, Vector, Widget, layout, mouse, + overlay as iced_overlay, renderer, }; #[must_use] @@ -37,76 +37,97 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> { where Drawer: Into>, { - let cosmic_theme::Spacing { - space_xxs, - space_s, - space_m, - space_l, - .. - } = crate::theme::active().cosmic().spacing; + #[inline(never)] + fn inner<'a, Message: Clone + 'static>( + title: Option>, + header_actions: Vec>, + header_opt: Option>, + footer_opt: Option>, + drawer: Element<'a, Message>, + on_close: Message, + max_width: f32, + ) -> Element<'a, Message> { + let cosmic_theme::Spacing { + space_xxs, + space_s, + space_m, + space_l, + .. + } = crate::theme::active().cosmic().spacing; - let horizontal_padding = if max_width < 392.0 { space_s } else { space_l }; + let horizontal_padding = if max_width < 392.0 { space_s } else { space_l }; - let header_row = row::with_capacity(3) - .width(Length::Fixed(480.0)) - .align_y(Alignment::Center) - .push( - row::with_children(header_actions) - .spacing(space_xxs) - .width(Length::FillPortion(1)), - ) - .push_maybe( - title.map(|title| text::heading(title).width(Length::FillPortion(1)).center()), - ) - .push( - button::text("Close") - .trailing_icon(icon::from_name("go-next-symbolic")) - .on_press(on_close) - .apply(container) - .width(Length::FillPortion(1)) - .align_x(Alignment::End), - ); - let header = column::with_capacity(2) - .width(Length::Fixed(480.0)) - .align_x(Alignment::Center) - .spacing(space_m) - .padding([space_m, horizontal_padding]) - .push(header_row) - .push_maybe(header_opt); - let footer = footer_opt.map(|element| { - container(element) + let header_row = row::with_capacity(3) .width(Length::Fixed(480.0)) .align_y(Alignment::Center) - .padding([space_xxs, horizontal_padding]) - }); - let pane = column::with_capacity(3) - .push(header) - .push( - scrollable(container(drawer.into()).padding([ - 0, - horizontal_padding, - if footer.is_some() { 0 } else { space_l }, - horizontal_padding, - ])) - .height(Length::Fill) - .width(Length::Shrink), - ) - .push_maybe(footer); + .push( + row::with_children(header_actions) + .spacing(space_xxs) + .width(Length::FillPortion(1)), + ) + .push_maybe( + title.map(|title| text::heading(title).width(Length::FillPortion(1)).center()), + ) + .push( + button::text("Close") + .trailing_icon(icon::from_name("go-next-symbolic")) + .on_press(on_close) + .apply(container) + .width(Length::FillPortion(1)) + .align_x(Alignment::End), + ); + let header = column::with_capacity(2) + .width(Length::Fixed(480.0)) + .align_x(Alignment::Center) + .spacing(space_m) + .padding([space_m, horizontal_padding]) + .push(header_row) + .push_maybe(header_opt); + let footer = footer_opt.map(|element| { + container(element) + .width(Length::Fixed(480.0)) + .align_y(Alignment::Center) + .padding([space_xxs, horizontal_padding]) + }); + let pane = column::with_capacity(3) + .push(header) + .push( + scrollable(container(drawer).padding([ + 0, + horizontal_padding, + if footer.is_some() { 0 } else { space_l }, + horizontal_padding, + ])) + .height(Length::Fill) + .width(Length::Shrink), + ) + .push_maybe(footer); - // XXX new limits do not exactly handle the max width well for containers - // XXX this is a hack to get around that - container( - LayerContainer::new(pane) - .layer(cosmic_theme::Layer::Primary) - .class(crate::style::Container::ContextDrawer) - .width(Length::Fill) - .height(Length::Fill) - .max_width(max_width), + // XXX new limits do not exactly handle the max width well for containers + // XXX this is a hack to get around that + container( + LayerContainer::new(pane) + .layer(cosmic_theme::Layer::Primary) + .class(crate::style::Container::ContextDrawer) + .width(Length::Fill) + .height(Length::Fill) + .max_width(max_width), + ) + .width(Length::Fill) + .height(Length::Fill) + .align_x(Alignment::End) + .into() + } + + inner( + title, + header_actions, + header_opt, + footer_opt, + drawer.into(), + on_close, + max_width, ) - .width(Length::Fill) - .height(Length::Fill) - .align_x(Alignment::End) - .into() } /// Creates an empty [`ContextDrawer`]. @@ -149,6 +170,7 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> { } // Optionally assigns message to `on_close` event. + #[inline] pub fn on_close_maybe(mut self, message: Option) -> Self { self.on_close = message; self diff --git a/src/widget/flex_row/widget.rs b/src/widget/flex_row/widget.rs index e343757..264201c 100644 --- a/src/widget/flex_row/widget.rs +++ b/src/widget/flex_row/widget.rs @@ -6,8 +6,8 @@ use derive_setters::Setters; use iced_core::event::{self, Event}; use iced_core::widget::{Operation, Tree}; use iced_core::{ - layout, mouse, overlay, renderer, Clipboard, Layout, Length, Padding, Rectangle, Shell, Vector, - Widget, + Clipboard, Layout, Length, Padding, Rectangle, Shell, Vector, Widget, layout, mouse, overlay, + renderer, }; /// Responsively generates rows and columns of widgets based on its dimensions. @@ -78,6 +78,7 @@ impl<'a, Message> FlexRow<'a, Message> { } /// Sets the space between each column and row. + #[inline] pub const fn spacing(mut self, spacing: u16) -> Self { self.column_spacing = spacing; self.row_spacing = spacing; diff --git a/src/widget/frames.rs b/src/widget/frames.rs index 7b6783c..1c379ac 100644 --- a/src/widget/frames.rs +++ b/src/widget/frames.rs @@ -10,17 +10,17 @@ use std::time::{Duration, Instant}; use ::image as image_rs; use iced_core::image::Renderer as ImageRenderer; use iced_core::mouse::Cursor; -use iced_core::widget::{tree, Tree}; +use iced_core::widget::{Tree, tree}; use iced_core::{ - event, layout, renderer, window, Clipboard, ContentFit, Element, Event, Layout, Length, - Rectangle, Shell, Size, Vector, Widget, + Clipboard, ContentFit, Element, Event, Layout, Length, Rectangle, Shell, Size, Vector, Widget, + event, layout, renderer, window, }; use iced_runtime::Command; use iced_widget::image::{self, Handle}; +use image_rs::AnimationDecoder; use image_rs::codecs::gif::GifDecoder; use image_rs::codecs::png::PngDecoder; use image_rs::codecs::webp::WebPDecoder; -use image_rs::AnimationDecoder; #[cfg(not(feature = "tokio"))] use iced_futures::futures::{AsyncRead, AsyncReadExt}; @@ -61,6 +61,7 @@ pub struct Frames { } impl fmt::Debug for Frames { + #[cold] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Frames").finish() } @@ -95,31 +96,36 @@ impl Frames { /// Load [`Frames`] from the supplied path pub fn load_from_path(path: impl AsRef) -> Command> { - #[cfg(feature = "tokio")] - use tokio::fs::File; - #[cfg(feature = "tokio")] - use tokio::io::BufReader; + #[inline(never)] + fn inner(path: &Path) -> Command> { + #[cfg(feature = "tokio")] + use tokio::fs::File; + #[cfg(feature = "tokio")] + use tokio::io::BufReader; - #[cfg(not(feature = "tokio"))] - use async_fs::File; - #[cfg(not(feature = "tokio"))] - use iced_futures::futures::io::BufReader; + #[cfg(not(feature = "tokio"))] + use async_fs::File; + #[cfg(not(feature = "tokio"))] + use iced_futures::futures::io::BufReader; - let path = path.as_ref().to_path_buf(); + let path = path.as_ref().to_path_buf(); - let f = async move { - let image_type = match &path.extension() { - Some(ext) if ext == &OsStr::new("gif") => ImageType::Gif, - Some(ext) if ext == &OsStr::new("apng") => ImageType::Apng, - Some(ext) if ext == &OsStr::new("webp") => ImageType::WebP, - _ => return Err(Error::Extension), + let f = async move { + let image_type = match &path.extension() { + Some(ext) if ext == &OsStr::new("gif") => ImageType::Gif, + Some(ext) if ext == &OsStr::new("apng") => ImageType::Apng, + Some(ext) if ext == &OsStr::new("webp") => ImageType::WebP, + _ => return Err(Error::Extension), + }; + let reader = BufReader::new(File::open(path).await?); + + Self::from_reader(reader, image_type).await }; - let reader = BufReader::new(File::open(path).await?); - Self::from_reader(reader, image_type).await - }; + Command::perform(f, std::convert::identity) + } - Command::perform(f, std::convert::identity) + inner(path.as_ref()) } /// Decode [`Frames`] from the supplied async reader diff --git a/src/widget/grid/widget.rs b/src/widget/grid/widget.rs index f09b373..8e9efc7 100644 --- a/src/widget/grid/widget.rs +++ b/src/widget/grid/widget.rs @@ -105,6 +105,7 @@ impl<'a, Message> Grid<'a, Message> { self } + #[inline] pub fn insert_row(mut self) -> Self { self.row += 1; self.column = 1; diff --git a/src/widget/header_bar.rs b/src/widget/header_bar.rs index 32bfa27..638bff5 100644 --- a/src/widget/header_bar.rs +++ b/src/widget/header_bar.rs @@ -2,11 +2,11 @@ // SPDX-License-Identifier: MPL-2.0 use crate::cosmic_theme::{Density, Spacing}; -use crate::{theme, widget, Element}; +use crate::{Element, theme, widget}; use apply::Apply; use derive_setters::Setters; use iced::Length; -use iced_core::{widget::tree, Vector, Widget}; +use iced_core::{Vector, Widget, widget::tree}; use std::borrow::Cow; #[must_use] @@ -109,6 +109,7 @@ impl<'a, Message: Clone + 'static> HeaderBar<'a, Message> { /// Build the widget #[must_use] + #[inline] pub fn build(self) -> HeaderBarWidget<'a, Message> { HeaderBarWidget { header_bar_inner: self.view(), diff --git a/src/widget/icon/handle.rs b/src/widget/icon/handle.rs index 3a2db2c..2d30427 100644 --- a/src/widget/icon/handle.rs +++ b/src/widget/icon/handle.rs @@ -17,6 +17,7 @@ pub struct Handle { } impl Handle { + #[inline] pub fn icon(self) -> Icon { super::icon(self) } @@ -53,13 +54,17 @@ pub fn from_raster_bytes( + std::marker::Sync + 'static, ) -> Handle { - Handle { - symbolic: false, - data: match bytes.into() { - Cow::Owned(b) => Data::Image(image::Handle::from_bytes(b)), - Cow::Borrowed(b) => Data::Image(image::Handle::from_bytes(b)), - }, + fn inner(bytes: Cow<'static, [u8]>) -> Handle { + Handle { + symbolic: false, + data: match bytes { + Cow::Owned(b) => Data::Image(image::Handle::from_bytes(b)), + Cow::Borrowed(b) => Data::Image(image::Handle::from_bytes(b)), + }, + } } + + inner(bytes.into()) } /// Create an image handle from RGBA data, where you must define the width and height. @@ -71,13 +76,19 @@ pub fn from_raster_pixels( + std::marker::Send + std::marker::Sync, ) -> Handle { - Handle { - symbolic: false, - data: match pixels.into() { - Cow::Owned(pixels) => Data::Image(image::Handle::from_rgba(width, height, pixels)), - Cow::Borrowed(pixels) => Data::Image(image::Handle::from_rgba(width, height, pixels)), - }, + fn inner(width: u32, height: u32, pixels: Cow<'static, [u8]>) -> Handle { + Handle { + symbolic: false, + data: match pixels { + Cow::Owned(pixels) => Data::Image(image::Handle::from_rgba(width, height, pixels)), + Cow::Borrowed(pixels) => { + Data::Image(image::Handle::from_rgba(width, height, pixels)) + } + }, + } } + + inner(width, height, pixels.into()) } /// Create a SVG handle from memory. diff --git a/src/widget/icon/named.rs b/src/widget/icon/named.rs index 055b2e4..da5c467 100644 --- a/src/widget/icon/named.rs +++ b/src/widget/icon/named.rs @@ -113,6 +113,7 @@ impl Named { None } + #[inline] pub fn handle(self) -> Handle { Handle { symbolic: self.symbolic, @@ -120,6 +121,7 @@ impl Named { } } + #[inline] pub fn icon(self) -> Icon { let size = self.size; @@ -133,18 +135,21 @@ impl Named { } impl From for Handle { + #[inline] fn from(builder: Named) -> Self { builder.handle() } } impl From for Icon { + #[inline] fn from(builder: Named) -> Self { builder.icon() } } impl From for crate::Element<'_, Message> { + #[inline] fn from(builder: Named) -> Self { builder.icon().into() } diff --git a/src/widget/layer_container.rs b/src/widget/layer_container.rs index f442bc5..74521b3 100644 --- a/src/widget/layer_container.rs +++ b/src/widget/layer_container.rs @@ -69,6 +69,7 @@ where /// Sets the width of the [`self.`]. #[must_use] + #[inline] pub fn width(mut self, width: Length) -> Self { self.container = self.container.width(width); self @@ -76,6 +77,7 @@ where /// Sets the height of the [`LayerContainer`]. #[must_use] + #[inline] pub fn height(mut self, height: Length) -> Self { self.container = self.container.height(height); self @@ -83,6 +85,7 @@ where /// Sets the maximum width of the [`LayerContainer`]. #[must_use] + #[inline] pub fn max_width(mut self, max_width: f32) -> Self { self.container = self.container.max_width(max_width); self @@ -90,6 +93,7 @@ where /// Sets the maximum height of the [`LayerContainer`] in pixels. #[must_use] + #[inline] pub fn max_height(mut self, max_height: f32) -> Self { self.container = self.container.max_height(max_height); self @@ -97,6 +101,7 @@ where /// Sets the content alignment for the horizontal axis of the [`LayerContainer`]. #[must_use] + #[inline] pub fn align_x(mut self, alignment: Alignment) -> Self { self.container = self.container.align_x(alignment); self @@ -104,6 +109,7 @@ where /// Sets the content alignment for the vertical axis of the [`LayerContainer`]. #[must_use] + #[inline] pub fn align_y(mut self, alignment: Alignment) -> Self { self.container = self.container.align_y(alignment); self @@ -111,6 +117,7 @@ where /// Centers the contents in the horizontal axis of the [`LayerContainer`]. #[must_use] + #[inline] pub fn center_x(mut self, width: Length) -> Self { self.container = self.container.center_x(width); self @@ -118,6 +125,7 @@ where /// Centers the contents in the vertical axis of the [`LayerContainer`]. #[must_use] + #[inline] pub fn center_y(mut self, height: Length) -> Self { self.container = self.container.center_y(height); self @@ -125,6 +133,7 @@ where /// Centers the contents in the horizontal and vertical axis of the [`Container`]. #[must_use] + #[inline] pub fn center(mut self, length: Length) -> Self { self.container = self.container.center(length); self diff --git a/src/widget/list/column.rs b/src/widget/list/column.rs index 1a9b734..d79d520 100644 --- a/src/widget/list/column.rs +++ b/src/widget/list/column.rs @@ -5,11 +5,11 @@ use iced_core::Padding; use iced_widget::container::Catalog; use crate::{ - theme, + Apply, Element, theme, widget::{container, divider, vertical_space}, - Apply, Element, }; +#[inline] pub fn list_column<'a, Message: 'static>() -> ListColumn<'a, Message> { ListColumn::default() } @@ -42,48 +42,61 @@ impl Default for ListColumn<'_, Message> { } impl<'a, Message: 'static> ListColumn<'a, Message> { + #[inline] pub fn new() -> Self { Self::default() } #[allow(clippy::should_implement_trait)] - pub fn add(mut self, item: impl Into>) -> Self { - if !self.children.is_empty() { - self.children.push( - container(divider::horizontal::default()) - .padding([0, self.divider_padding]) - .into(), - ); + pub fn add(self, item: impl Into>) -> Self { + #[inline(never)] + fn inner<'a, Message: 'static>( + mut this: ListColumn<'a, Message>, + item: Element<'a, Message>, + ) -> ListColumn<'a, Message> { + if !this.children.is_empty() { + this.children.push( + container(divider::horizontal::default()) + .padding([0, this.divider_padding]) + .into(), + ); + } + + // Ensure a minimum height of 32. + let list_item = iced::widget::row![ + container(item).align_y(iced::Alignment::Center), + vertical_space().height(iced::Length::Fixed(32.)) + ] + .padding(this.list_item_padding) + .align_y(iced::Alignment::Center); + + this.children.push(list_item.into()); + this } - // Ensure a minimum height of 32. - let list_item = iced::widget::row![ - container(item).align_y(iced::Alignment::Center), - vertical_space().height(iced::Length::Fixed(32.)) - ] - .padding(self.list_item_padding) - .align_y(iced::Alignment::Center); - - self.children.push(list_item.into()); - self + inner(self, item.into()) } + #[inline] pub fn spacing(mut self, spacing: u16) -> Self { self.spacing = spacing; self } /// Sets the style variant of this [`Circular`]. + #[inline] pub fn style(mut self, style: ::Class<'a>) -> Self { self.style = style; self } + #[inline] pub fn padding(mut self, padding: impl Into) -> Self { self.padding = padding.into(); self } + #[inline] pub fn divider_padding(mut self, padding: u16) -> Self { self.divider_padding = padding; self diff --git a/src/widget/nav_bar.rs b/src/widget/nav_bar.rs index 5a32b4a..fef3cbe 100644 --- a/src/widget/nav_bar.rs +++ b/src/widget/nav_bar.rs @@ -7,13 +7,13 @@ use apply::Apply; use iced::{ - clipboard::{dnd::DndAction, mime::AllowedMimeTypes}, Background, Length, + clipboard::{dnd::DndAction, mime::AllowedMimeTypes}, }; use iced_core::{Border, Color, Shadow}; -use crate::widget::{container, menu, scrollable, segmented_button, Container, Icon}; -use crate::{theme, Theme}; +use crate::widget::{Container, Icon, container, menu, scrollable, segmented_button}; +use crate::{Theme, theme}; use super::dnd_destination::DragId; @@ -62,16 +62,19 @@ pub struct NavBar<'a, Message> { } impl<'a, Message: Clone + 'static> NavBar<'a, Message> { + #[inline] pub fn close_icon(mut self, close_icon: Icon) -> Self { self.segmented_button = self.segmented_button.close_icon(close_icon); self } + #[inline] pub fn context_menu(mut self, context_menu: Option>>) -> Self { self.segmented_button = self.segmented_button.context_menu(context_menu); self } + #[inline] pub fn drag_id(mut self, id: DragId) -> Self { self.segmented_button = self.segmented_button.drag_id(id); self @@ -79,6 +82,7 @@ impl<'a, Message: Clone + 'static> NavBar<'a, Message> { /// Pre-convert this widget into the [`Container`] widget that it becomes. #[must_use] + #[inline] pub fn into_container(self) -> Container<'a, Message, crate::Theme, crate::Renderer> { Container::from(self) } diff --git a/src/widget/nav_bar_toggle.rs b/src/widget/nav_bar_toggle.rs index 2a31568..dd4b788 100644 --- a/src/widget/nav_bar_toggle.rs +++ b/src/widget/nav_bar_toggle.rs @@ -16,7 +16,7 @@ pub struct NavBarToggle { } #[must_use] -pub fn nav_bar_toggle() -> NavBarToggle { +pub const fn nav_bar_toggle() -> NavBarToggle { NavBarToggle { active: false, on_toggle: None, diff --git a/src/widget/rectangle_tracker/subscription.rs b/src/widget/rectangle_tracker/subscription.rs index e49946d..541862c 100644 --- a/src/widget/rectangle_tracker/subscription.rs +++ b/src/widget/rectangle_tracker/subscription.rs @@ -1,15 +1,17 @@ use iced::{ - futures::{ - channel::mpsc::{unbounded, UnboundedReceiver}, - stream, StreamExt, - }, Rectangle, + futures::{ + StreamExt, + channel::mpsc::{UnboundedReceiver, unbounded}, + stream, + }, }; use iced_futures::Subscription; use std::{collections::HashMap, fmt::Debug, hash::Hash}; use super::RectangleTracker; +#[cold] pub fn rectangle_tracker_subscription< I: 'static + Hash + Copy + Send + Sync + Debug, R: 'static + Hash + Copy + Send + Sync + Debug + Eq, diff --git a/src/widget/segmented_button/model/builder.rs b/src/widget/segmented_button/model/builder.rs index c7e3239..d8070aa 100644 --- a/src/widget/segmented_button/model/builder.rs +++ b/src/widget/segmented_button/model/builder.rs @@ -32,6 +32,7 @@ where } /// Consumes the builder and returns the model. + #[inline] pub fn build(self) -> Model { self.0 } @@ -43,6 +44,7 @@ where { /// Activates the newly-inserted item. #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn activate(mut self) -> Self { self.model.0.activate(self.id); self @@ -50,6 +52,7 @@ where /// Defines that the close button should appear #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn closable(mut self) -> Self { self.model.0.closable_set(self.id, true); self @@ -60,6 +63,7 @@ where /// The secondary map internally uses a `Vec`, so should only be used for data that /// is commonly associated. #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn secondary(self, map: &mut SecondaryMap, data: Data) -> Self { map.insert(self.id, data); self @@ -69,6 +73,7 @@ where /// /// Sparse maps internally use a `HashMap`, for data that is sparsely associated. #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn secondary_sparse( self, map: &mut SparseSecondaryMap, @@ -90,11 +95,13 @@ where /// .build() /// ``` #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn data(mut self, data: Data) -> Self { self.model.0.data_set(self.id, data); self } + #[inline] pub fn divider_above(mut self) -> Self { self.model.0.divider_above_set(self.id, true); self @@ -115,6 +122,7 @@ where /// Define the position of the newly-inserted item. #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn position(mut self, position: u16) -> Self { self.model.0.position_set(self.id, position); self @@ -122,6 +130,7 @@ where /// Swap the position with another item in the model. #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn position_swap(mut self, other: Entity) -> Self { self.model.0.position_swap(self.id, other); self diff --git a/src/widget/segmented_button/model/entity.rs b/src/widget/segmented_button/model/entity.rs index 02a7d37..a382124 100644 --- a/src/widget/segmented_button/model/entity.rs +++ b/src/widget/segmented_button/model/entity.rs @@ -25,6 +25,7 @@ where /// model.insert().text("Item A").activate(); /// ``` #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn activate(self) -> Self { self.model.activate(self.id); self @@ -40,6 +41,7 @@ where /// model.insert().text("Item A").secondary(&mut secondary_data, String::new("custom data")); /// ``` #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn secondary(self, map: &mut SecondaryMap, data: Data) -> Self { map.insert(self.id, data); self @@ -54,6 +56,7 @@ where /// model.insert().text("Item A").secondary(&mut secondary_data, String::new("custom data")); /// ``` #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn secondary_sparse( self, map: &mut SparseSecondaryMap, @@ -65,6 +68,7 @@ where /// Shows a close button for this item. #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn closable(self) -> Self { self.model.closable_set(self.id, true); self @@ -78,12 +82,14 @@ where /// model.insert().text("Item A").data(String::from("custom string")); /// ``` #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn data(self, data: Data) -> Self { self.model.data_set(self.id, data); self } #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn divider_above(self, divider_above: bool) -> Self { self.model.divider_above_set(self.id, divider_above); self @@ -95,6 +101,7 @@ where /// model.insert().text("Item A").icon(IconSource::from("icon-a")); /// ``` #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn icon(self, icon: impl Into) -> Self { self.model.icon_set(self.id, icon.into()); self @@ -106,11 +113,13 @@ where /// let id = model.insert("Item A").id(); /// ``` #[must_use] - pub fn id(self) -> Entity { + #[inline] + pub const fn id(self) -> Entity { self.id } #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn indent(self, indent: u16) -> Self { self.model.indent_set(self.id, indent); self @@ -118,6 +127,7 @@ where /// Define the position of the item. #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn position(self, position: u16) -> Self { self.model.position_set(self.id, position); self @@ -125,6 +135,7 @@ where /// Swap the position with another item in the model. #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)] + #[inline] pub fn position_swap(self, other: Entity) -> Self { self.model.position_swap(self.id, other); self diff --git a/src/widget/segmented_button/model/mod.rs b/src/widget/segmented_button/model/mod.rs index c24fe85..83a1702 100644 --- a/src/widget/segmented_button/model/mod.rs +++ b/src/widget/segmented_button/model/mod.rs @@ -89,11 +89,13 @@ where /// ```ignore /// model.activate(id); /// ``` + #[inline] pub fn activate(&mut self, id: Entity) { Selectable::activate(self, id); } /// Activates the item at the given position, returning true if it was activated. + #[inline] pub fn activate_position(&mut self, position: u16) -> bool { if let Some(entity) = self.entity_at(position) { self.activate(entity); @@ -113,6 +115,7 @@ where /// .build(); /// ``` #[must_use] + #[inline] pub fn builder() -> ModelBuilder { ModelBuilder::default() } @@ -126,6 +129,7 @@ where /// ```ignore /// model.clear(); /// ``` + #[inline] pub fn clear(&mut self) { for entity in self.order.clone() { self.remove(entity); @@ -133,6 +137,7 @@ where } /// Shows or hides the item's close button. + #[inline] pub fn closable_set(&mut self, id: Entity, closable: bool) { if let Some(settings) = self.items.get_mut(id) { settings.closable = closable; @@ -146,6 +151,7 @@ where /// println!("ID is still valid"); /// } /// ``` + #[inline] pub fn contains_item(&self, id: Entity) -> bool { self.items.contains_key(id) } @@ -203,6 +209,7 @@ where .and_then(|storage| storage.remove(id)); } + #[inline] pub fn divider_above(&self, id: Entity) -> Option { self.divider_aboves.get(id).copied() } @@ -215,6 +222,7 @@ where self.divider_aboves.insert(id, divider_above) } + #[inline] pub fn divider_above_remove(&mut self, id: Entity) -> Option { self.divider_aboves.remove(id) } @@ -224,6 +232,7 @@ where /// ```ignore /// model.enable(id, true); /// ``` + #[inline] pub fn enable(&mut self, id: Entity, enable: bool) { if let Some(e) = self.items.get_mut(id) { e.enabled = enable; @@ -232,6 +241,7 @@ where /// Get the item that is located at a given position. #[must_use] + #[inline] pub fn entity_at(&mut self, position: u16) -> Option { self.order.get(position as usize).copied() } @@ -243,6 +253,7 @@ where /// println!("has icon: {:?}", icon); /// } /// ``` + #[inline] pub fn icon(&self, id: Entity) -> Option<&Icon> { self.icons.get(id) } @@ -254,6 +265,7 @@ where /// println!("previously had icon: {:?}", old_icon); /// } /// ``` + #[inline] pub fn icon_set(&mut self, id: Entity, icon: Icon) -> Option { if !self.contains_item(id) { return None; @@ -268,6 +280,7 @@ where /// if let Some(old_icon) = model.icon_remove(id) { /// println!("previously had icon: {:?}", old_icon); /// } + #[inline] pub fn icon_remove(&mut self, id: Entity) -> Option { self.icons.remove(id) } @@ -278,6 +291,7 @@ where /// let id = model.insert().text("Item A").icon("custom-icon").id(); /// ``` #[must_use] + #[inline] pub fn insert(&mut self) -> EntityMut { let id = self.items.insert(Settings::default()); self.order.push_back(id); @@ -286,14 +300,16 @@ where /// Check if the given ID is the active ID. #[must_use] + #[inline] pub fn is_active(&self, id: Entity) -> bool { ::is_active(self, id) } /// Whether the item should contain a close button. #[must_use] + #[inline] pub fn is_closable(&self, id: Entity) -> bool { - self.items.get(id).map_or(false, |e| e.closable) + self.items.get(id).map(|e| e.closable).unwrap_or_default() } /// Check if the item is enabled. @@ -306,11 +322,13 @@ where /// } /// ``` #[must_use] + #[inline] pub fn is_enabled(&self, id: Entity) -> bool { - self.items.get(id).map_or(false, |e| e.enabled) + self.items.get(id).map(|e| e.enabled).unwrap_or_default() } /// Get number of items in the model. + #[inline] pub fn len(&self) -> usize { self.order.len() } @@ -320,10 +338,12 @@ where self.order.iter().copied() } + #[inline] pub fn indent(&self, id: Entity) -> Option { self.indents.get(id).copied() } + #[inline] pub fn indent_set(&mut self, id: Entity, indent: u16) -> Option { if !self.contains_item(id) { return None; @@ -332,6 +352,7 @@ where self.indents.insert(id, indent) } + #[inline] pub fn indent_remove(&mut self, id: Entity) -> Option { self.indents.remove(id) } @@ -343,6 +364,7 @@ where /// println!("found item at {}", position); /// } #[must_use] + #[inline] pub fn position(&self, id: Entity) -> Option { #[allow(clippy::cast_possible_truncation)] self.order.iter().position(|k| *k == id).map(|v| v as u16) @@ -356,9 +378,7 @@ where /// } /// ``` pub fn position_set(&mut self, id: Entity, position: u16) -> Option { - let Some(index) = self.position(id) else { - return None; - }; + let index = self.position(id)?; self.order.remove(index as usize); @@ -415,6 +435,7 @@ where /// println!("{:?} has text {text}", id); /// } /// ``` + #[inline] pub fn text(&self, id: Entity) -> Option<&str> { self.text.get(id).map(Cow::as_ref) } @@ -439,6 +460,7 @@ where /// if let Some(old_text) = model.text_remove(id) { /// println!("{:?} had text {}", id, old_text); /// } + #[inline] pub fn text_remove(&mut self, id: Entity) -> Option> { self.text.remove(id) } diff --git a/src/widget/segmented_button/model/selection.rs b/src/widget/segmented_button/model/selection.rs index 1366c18..c092765 100644 --- a/src/widget/segmented_button/model/selection.rs +++ b/src/widget/segmented_button/model/selection.rs @@ -39,6 +39,7 @@ impl Selectable for Model { } } + #[inline] fn is_active(&self, id: Entity) -> bool { self.selection.active == id } @@ -47,23 +48,27 @@ impl Selectable for Model { impl Model { /// Get an immutable reference to the data associated with the active item. #[must_use] + #[inline] pub fn active_data(&self) -> Option<&Data> { self.data(self.active()) } /// Get a mutable reference to the data associated with the active item. #[must_use] + #[inline] pub fn active_data_mut(&mut self) -> Option<&mut Data> { self.data_mut(self.active()) } /// Deactivates the active item. + #[inline] pub fn deactivate(&mut self) { Selectable::deactivate(self, Entity::default()); } /// The ID of the active item. #[must_use] + #[inline] pub fn active(&self) -> Entity { self.selection.active } @@ -86,10 +91,12 @@ impl Selectable for Model { } } + #[inline] fn deactivate(&mut self, id: Entity) { self.selection.active.remove(&id); } + #[inline] fn is_active(&self, id: Entity) -> bool { self.selection.active.contains(&id) } @@ -97,11 +104,13 @@ impl Selectable for Model { impl Model { /// Deactivates the item in the model. + #[inline] pub fn deactivate(&mut self, id: Entity) { Selectable::deactivate(self, id); } /// The IDs of the active items. + #[inline] pub fn active(&self) -> impl Iterator + '_ { self.selection.active.iter().copied() } diff --git a/src/widget/segmented_button/widget.rs b/src/widget/segmented_button/widget.rs index 9bdc9ad..2a05d44 100644 --- a/src/widget/segmented_button/widget.rs +++ b/src/widget/segmented_button/widget.rs @@ -20,7 +20,7 @@ use iced::{ event, keyboard, mouse, touch, }; use iced_core::mouse::ScrollDelta; -use iced_core::text::{LineHeight, Paragraph, Renderer as TextRenderer, Shaping, Wrapping}; +use iced_core::text::{LineHeight, Renderer as TextRenderer, Shaping, Wrapping}; use iced_core::widget::{self, operation, tree}; use iced_core::{Border, Gradient, Point, Renderer as IcedRenderer, Shadow, Text}; use iced_core::{Clipboard, Layout, Shell, Widget, layout, renderer, widget::Tree}; @@ -158,6 +158,7 @@ where Model: Selectable, SelectionMode: Default, { + #[inline] pub fn new(model: &'a Model) -> Self { Self { model, @@ -1726,6 +1727,7 @@ impl Id { /// /// This function produces a different [`Id`] every time it is called. #[must_use] + #[inline] pub fn unique() -> Self { Self(widget::Id::unique()) } diff --git a/src/widget/settings/item.rs b/src/widget/settings/item.rs index 36cc555..0a5406f 100644 --- a/src/widget/settings/item.rs +++ b/src/widget/settings/item.rs @@ -19,11 +19,19 @@ pub fn item<'a, Message: 'static>( title: impl Into> + 'a, widget: impl Into> + 'a, ) -> Row<'a, Message> { - item_row(vec![ - text(title).wrapping(Wrapping::Word).into(), - horizontal_space().into(), - widget.into(), - ]) + #[inline(never)] + fn inner<'a, Message: 'static>( + title: Cow<'a, str>, + widget: Element<'a, Message>, + ) -> Row<'a, Message> { + item_row(vec![ + text(title).wrapping(Wrapping::Word).into(), + horizontal_space().into(), + widget, + ]) + } + + inner(title.into(), widget.into()) } /// A settings item aligned in a row @@ -41,13 +49,21 @@ pub fn flex_item<'a, Message: 'static>( title: impl Into> + 'a, widget: impl Into> + 'a, ) -> FlexRow<'a, Message> { - flex_item_row(vec![ - text(title) - .wrapping(Wrapping::Word) - .width(Length::Fill) - .into(), - container(widget).into(), - ]) + #[inline(never)] + fn inner<'a, Message: 'static>( + title: Cow<'a, str>, + widget: Element<'a, Message>, + ) -> FlexRow<'a, Message> { + flex_item_row(vec![ + text(title) + .wrapping(Wrapping::Word) + .width(Length::Fill) + .into(), + container(widget).into(), + ]) + } + + inner(title.into(), widget.into()) } /// A settings item aligned in a flex row @@ -88,15 +104,16 @@ pub struct Item<'a, Message> { impl<'a, Message: 'static> Item<'a, Message> { /// Assigns a control to the item. pub fn control(self, widget: impl Into>) -> Row<'a, Message> { - item_row(self.control_(widget)) + item_row(self.control_(widget.into())) } /// Assigns a control which flexes. pub fn flex_control(self, widget: impl Into>) -> FlexRow<'a, Message> { - flex_item_row(self.control_(widget)) + flex_item_row(self.control_(widget.into())) } - fn control_(self, widget: impl Into>) -> Vec> { + #[inline(never)] + fn control_(self, widget: Element<'a, Message>) -> Vec> { let mut contents = Vec::with_capacity(4); if let Some(icon) = self.icon { diff --git a/src/widget/text.rs b/src/widget/text.rs index b542f2e..37e85b8 100644 --- a/src/widget/text.rs +++ b/src/widget/text.rs @@ -26,72 +26,117 @@ pub enum Typography { /// [`Text`] widget with the Title 1 typography preset. pub fn title1<'a>(text: impl Into> + 'a) -> Text<'a, crate::Theme, Renderer> { - Text::new(text.into()) - .size(35.0) - .line_height(LineHeight::Absolute(52.0.into())) - .font(crate::font::semibold()) + #[inline(never)] + fn inner(text: Cow) -> Text { + Text::new(text) + .size(35.0) + .line_height(LineHeight::Absolute(52.0.into())) + .font(crate::font::semibold()) + } + + inner(text.into()) } /// [`Text`] widget with the Title 2 typography preset. pub fn title2<'a>(text: impl Into> + 'a) -> Text<'a, crate::Theme, Renderer> { - Text::new(text.into()) - .size(29.0) - .line_height(LineHeight::Absolute(43.0.into())) - .font(crate::font::semibold()) + #[inline(never)] + fn inner(text: Cow) -> Text { + Text::new(text) + .size(29.0) + .line_height(LineHeight::Absolute(43.0.into())) + .font(crate::font::semibold()) + } + + inner(text.into()) } /// [`Text`] widget with the Title 3 typography preset. pub fn title3<'a>(text: impl Into> + 'a) -> Text<'a, crate::Theme, Renderer> { - Text::new(text.into()) - .size(24.0) - .line_height(LineHeight::Absolute(36.0.into())) - .font(crate::font::bold()) + #[inline(never)] + fn inner(text: Cow) -> Text { + Text::new(text) + .size(24.0) + .line_height(LineHeight::Absolute(36.0.into())) + .font(crate::font::bold()) + } + + inner(text.into()) } /// [`Text`] widget with the Title 4 typography preset. pub fn title4<'a>(text: impl Into> + 'a) -> Text<'a, crate::Theme, Renderer> { - Text::new(text.into()) - .size(20.0) - .line_height(LineHeight::Absolute(30.0.into())) - .font(crate::font::bold()) + #[inline(never)] + fn inner(text: Cow) -> Text { + Text::new(text) + .size(20.0) + .line_height(LineHeight::Absolute(30.0.into())) + .font(crate::font::bold()) + } + + inner(text.into()) } /// [`Text`] widget with the Heading typography preset. pub fn heading<'a>(text: impl Into> + 'a) -> Text<'a, crate::Theme, Renderer> { - Text::new(text.into()) - .size(14.0) - .line_height(LineHeight::Absolute(iced::Pixels(21.0))) - .font(crate::font::bold()) + #[inline(never)] + fn inner(text: Cow) -> Text { + Text::new(text) + .size(14.0) + .line_height(LineHeight::Absolute(iced::Pixels(21.0))) + .font(crate::font::bold()) + } + + inner(text.into()) } /// [`Text`] widget with the Caption Heading typography preset. pub fn caption_heading<'a>(text: impl Into> + 'a) -> Text<'a, crate::Theme, Renderer> { - Text::new(text.into()) - .size(12.0) - .line_height(LineHeight::Absolute(iced::Pixels(17.0))) - .font(crate::font::semibold()) + #[inline(never)] + fn inner(text: Cow) -> Text { + Text::new(text) + .size(12.0) + .line_height(LineHeight::Absolute(iced::Pixels(17.0))) + .font(crate::font::semibold()) + } + + inner(text.into()) } /// [`Text`] widget with the Body typography preset. pub fn body<'a>(text: impl Into> + 'a) -> Text<'a, crate::Theme, Renderer> { - Text::new(text.into()) - .size(14.0) - .line_height(LineHeight::Absolute(21.0.into())) - .font(crate::font::default()) + #[inline(never)] + fn inner(text: Cow) -> Text { + Text::new(text) + .size(14.0) + .line_height(LineHeight::Absolute(21.0.into())) + .font(crate::font::default()) + } + + inner(text.into()) } /// [`Text`] widget with the Caption typography preset. pub fn caption<'a>(text: impl Into> + 'a) -> Text<'a, crate::Theme, Renderer> { - Text::new(text.into()) - .size(12.0) - .line_height(LineHeight::Absolute(17.0.into())) - .font(crate::font::default()) + #[inline(never)] + fn inner(text: Cow) -> Text { + Text::new(text) + .size(12.0) + .line_height(LineHeight::Absolute(17.0.into())) + .font(crate::font::default()) + } + + inner(text.into()) } /// [`Text`] widget with the Monotext typography preset. pub fn monotext<'a>(text: impl Into> + 'a) -> Text<'a, crate::Theme, Renderer> { - Text::new(text.into()) - .size(14.0) - .line_height(LineHeight::Absolute(20.0.into())) - .font(crate::font::mono()) + #[inline(never)] + fn inner(text: Cow) -> Text { + Text::new(text) + .size(14.0) + .line_height(LineHeight::Absolute(20.0.into())) + .font(crate::font::mono()) + } + + inner(text.into()) } diff --git a/src/widget/toaster/mod.rs b/src/widget/toaster/mod.rs index 1acbce0..efd93a9 100644 --- a/src/widget/toaster/mod.rs +++ b/src/widget/toaster/mod.rs @@ -6,16 +6,14 @@ use std::collections::VecDeque; use std::rc::Rc; -use crate::widget::container; use crate::widget::Column; +use crate::widget::container; use iced::Task; use iced_core::Element; -use slotmap::new_key_type; use slotmap::SlotMap; +use slotmap::new_key_type; use widget::Toaster; -use crate::ext::CollectionWidget; - use super::column; use super::{button, icon, row, text}; @@ -106,6 +104,7 @@ pub struct Action { } impl std::fmt::Debug for Action { + #[cold] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Action") .field("description", &self.description)