fix: Use globals instead of thread-locals
Better support for multi-threaded applications, especially cosmic-comp rendering in parallel on multiple threads, each potentially accessing global configurations such as the active theme, icon_theme and more...
This commit is contained in:
parent
f655710d55
commit
b40839638a
16 changed files with 183 additions and 216 deletions
|
|
@ -218,15 +218,14 @@ where
|
||||||
self.app
|
self.app
|
||||||
.core()
|
.core()
|
||||||
.watch_config::<cosmic_theme::Theme>(
|
.watch_config::<cosmic_theme::Theme>(
|
||||||
if THEME
|
if if let ThemeType::System { prefer_dark, .. } =
|
||||||
.with(|t| {
|
THEME.lock().unwrap().theme_type
|
||||||
if let ThemeType::System { prefer_dark, .. } = t.borrow().theme_type {
|
{
|
||||||
prefer_dark
|
prefer_dark
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
.unwrap_or_else(|| self.app.core().system_theme_mode.is_dark)
|
||||||
.unwrap_or_else(|| self.app.core().system_theme_mode.is_dark)
|
|
||||||
{
|
{
|
||||||
cosmic_theme::DARK_THEME_ID
|
cosmic_theme::DARK_THEME_ID
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -427,14 +426,11 @@ impl<T: Application> Cosmic<T> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
THEME.with(move |t| {
|
THEME.lock().unwrap().set_theme(theme.theme_type);
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
|
||||||
cosmic_theme.set_theme(theme.theme_type);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::SystemThemeChange(keys, theme) => {
|
Message::SystemThemeChange(keys, theme) => {
|
||||||
let cur_is_dark = THEME.with(|t| t.borrow().theme_type.is_dark());
|
let cur_is_dark = THEME.lock().unwrap().theme_type.is_dark();
|
||||||
// Ignore updates if the current theme mode does not match.
|
// Ignore updates if the current theme mode does not match.
|
||||||
if cur_is_dark != theme.cosmic().is_dark {
|
if cur_is_dark != theme.cosmic().is_dark {
|
||||||
return iced::Command::none();
|
return iced::Command::none();
|
||||||
|
|
@ -443,8 +439,8 @@ impl<T: Application> Cosmic<T> {
|
||||||
// Record the last-known system theme in event that the current theme is custom.
|
// Record the last-known system theme in event that the current theme is custom.
|
||||||
self.app.core_mut().system_theme = theme.clone();
|
self.app.core_mut().system_theme = theme.clone();
|
||||||
let portal_accent = self.app.core().portal_accent;
|
let portal_accent = self.app.core().portal_accent;
|
||||||
THEME.with(move |t| {
|
{
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
let mut cosmic_theme = THEME.lock().unwrap();
|
||||||
|
|
||||||
// Only apply update if the theme is set to load a system theme
|
// Only apply update if the theme is set to load a system theme
|
||||||
if let ThemeType::System {
|
if let ThemeType::System {
|
||||||
|
|
@ -466,7 +462,7 @@ impl<T: Application> Cosmic<T> {
|
||||||
|
|
||||||
cosmic_theme.set_theme(new_theme.theme_type);
|
cosmic_theme.set_theme(new_theme.theme_type);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
@ -485,13 +481,13 @@ impl<T: Application> Cosmic<T> {
|
||||||
if !keys.contains(&"is_dark") {
|
if !keys.contains(&"is_dark") {
|
||||||
return iced::Command::none();
|
return iced::Command::none();
|
||||||
}
|
}
|
||||||
if THEME.with(|t| match t.borrow().theme_type {
|
if match THEME.lock().unwrap().theme_type {
|
||||||
ThemeType::System {
|
ThemeType::System {
|
||||||
theme: _,
|
theme: _,
|
||||||
prefer_dark,
|
prefer_dark,
|
||||||
} => prefer_dark.is_some(),
|
} => prefer_dark.is_some(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}) {
|
} {
|
||||||
return iced::Command::none();
|
return iced::Command::none();
|
||||||
}
|
}
|
||||||
let mut cmds = vec![self.app.system_theme_mode_update(&keys, &mode)];
|
let mut cmds = vec![self.app.system_theme_mode_update(&keys, &mode)];
|
||||||
|
|
@ -523,13 +519,13 @@ impl<T: Application> Cosmic<T> {
|
||||||
};
|
};
|
||||||
|
|
||||||
core.system_theme = new_theme.clone();
|
core.system_theme = new_theme.clone();
|
||||||
THEME.with(move |t| {
|
{
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
let mut cosmic_theme = THEME.lock().unwrap();
|
||||||
// Only apply update if the theme is set to load a system theme
|
// Only apply update if the theme is set to load a system theme
|
||||||
if let ThemeType::System { theme: _, .. } = cosmic_theme.theme_type {
|
if let ThemeType::System { theme: _, .. } = cosmic_theme.theme_type {
|
||||||
cosmic_theme.set_theme(new_theme.theme_type);
|
cosmic_theme.set_theme(new_theme.theme_type);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
return Command::batch(cmds);
|
return Command::batch(cmds);
|
||||||
}
|
}
|
||||||
|
|
@ -552,13 +548,13 @@ impl<T: Application> Cosmic<T> {
|
||||||
#[cfg(feature = "xdg-portal")]
|
#[cfg(feature = "xdg-portal")]
|
||||||
Message::DesktopSettings(crate::theme::portal::Desktop::ColorScheme(s)) => {
|
Message::DesktopSettings(crate::theme::portal::Desktop::ColorScheme(s)) => {
|
||||||
use ashpd::desktop::settings::ColorScheme;
|
use ashpd::desktop::settings::ColorScheme;
|
||||||
if THEME.with(|t| match t.borrow().theme_type {
|
if match THEME.lock().unwrap().theme_type {
|
||||||
ThemeType::System {
|
ThemeType::System {
|
||||||
theme: _,
|
theme: _,
|
||||||
prefer_dark,
|
prefer_dark,
|
||||||
} => prefer_dark.is_some(),
|
} => prefer_dark.is_some(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}) {
|
} {
|
||||||
return iced::Command::none();
|
return iced::Command::none();
|
||||||
}
|
}
|
||||||
let is_dark = match s {
|
let is_dark = match s {
|
||||||
|
|
@ -579,14 +575,14 @@ impl<T: Application> Cosmic<T> {
|
||||||
crate::theme::system_light()
|
crate::theme::system_light()
|
||||||
};
|
};
|
||||||
core.system_theme = new_theme.clone();
|
core.system_theme = new_theme.clone();
|
||||||
THEME.with(move |t| {
|
{
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
let mut cosmic_theme = THEME.lock().unwrap();
|
||||||
|
|
||||||
// Only apply update if the theme is set to load a system theme
|
// Only apply update if the theme is set to load a system theme
|
||||||
if let ThemeType::System { theme: _, .. } = cosmic_theme.theme_type {
|
if let ThemeType::System { theme: _, .. } = cosmic_theme.theme_type {
|
||||||
cosmic_theme.set_theme(new_theme.theme_type);
|
cosmic_theme.set_theme(new_theme.theme_type);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "xdg-portal")]
|
#[cfg(feature = "xdg-portal")]
|
||||||
|
|
@ -602,8 +598,8 @@ impl<T: Application> Cosmic<T> {
|
||||||
return iced::Command::none();
|
return iced::Command::none();
|
||||||
}
|
}
|
||||||
|
|
||||||
THEME.with(move |t| {
|
{
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
let mut cosmic_theme = THEME.lock().unwrap();
|
||||||
|
|
||||||
// Only apply update if the theme is set to load a system theme
|
// Only apply update if the theme is set to load a system theme
|
||||||
if let ThemeType::System {
|
if let ThemeType::System {
|
||||||
|
|
@ -616,7 +612,7 @@ impl<T: Application> Cosmic<T> {
|
||||||
prefer_dark,
|
prefer_dark,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "xdg-portal")]
|
#[cfg(feature = "xdg-portal")]
|
||||||
Message::DesktopSettings(crate::theme::portal::Desktop::Contrast(_)) => {
|
Message::DesktopSettings(crate::theme::portal::Desktop::Contrast(_)) => {
|
||||||
|
|
@ -631,7 +627,7 @@ impl<T: Application> Cosmic<T> {
|
||||||
crate::icon_theme::set_default(config.icon_theme.clone());
|
crate::icon_theme::set_default(config.icon_theme.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::config::COSMIC_TK.with(|tk| *tk.borrow_mut() = config);
|
*crate::config::COSMIC_TK.lock().unwrap() = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::Focus(f) => {
|
Message::Focus(f) => {
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ pub mod message {
|
||||||
pub use self::command::Command;
|
pub use self::command::Command;
|
||||||
pub use self::core::Core;
|
pub use self::core::Core;
|
||||||
pub use self::settings::Settings;
|
pub use self::settings::Settings;
|
||||||
use crate::config::CosmicTk;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::theme::THEME;
|
use crate::theme::THEME;
|
||||||
use crate::widget::{context_drawer, id_container, menu, nav_bar, popover};
|
use crate::widget::{context_drawer, id_container, menu, nav_bar, popover};
|
||||||
|
|
@ -58,7 +57,6 @@ use iced::Subscription;
|
||||||
use iced::{multi_window::Application as IcedApplication, window};
|
use iced::{multi_window::Application as IcedApplication, window};
|
||||||
#[cfg(any(not(feature = "winit"), not(feature = "multi-window")))]
|
#[cfg(any(not(feature = "winit"), not(feature = "multi-window")))]
|
||||||
use iced::{window, Application as IcedApplication};
|
use iced::{window, Application as IcedApplication};
|
||||||
use iced_core::mouse;
|
|
||||||
pub use message::Message;
|
pub use message::Message;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
#[cfg(feature = "single-instance")]
|
#[cfg(feature = "single-instance")]
|
||||||
|
|
@ -87,10 +85,7 @@ pub(crate) fn iced_settings<App: Application>(
|
||||||
crate::icon_theme::set_default(crate::config::icon_theme());
|
crate::icon_theme::set_default(crate::config::icon_theme());
|
||||||
}
|
}
|
||||||
|
|
||||||
THEME.with(move |t| {
|
THEME.lock().unwrap().set_theme(settings.theme.theme_type);
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
|
||||||
cosmic_theme.set_theme(settings.theme.theme_type);
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut iced = iced::Settings::with_flags((core, flags));
|
let mut iced = iced::Settings::with_flags((core, flags));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -375,10 +375,7 @@ pub fn run<App: Application>(autosize: bool, flags: App::Flags) -> iced::Result
|
||||||
core.set_window_width(width);
|
core.set_window_width(width);
|
||||||
core.set_window_height(height);
|
core.set_window_height(height);
|
||||||
|
|
||||||
THEME.with(move |t| {
|
THEME.lock().unwrap().set_theme(settings.theme.theme_type);
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
|
||||||
cosmic_theme.set_theme(settings.theme.theme_type);
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut iced = iced::Settings::with_flags((core, flags));
|
let mut iced = iced::Settings::with_flags((core, flags));
|
||||||
|
|
||||||
|
|
@ -435,11 +432,7 @@ pub fn padded_control<'a, Message>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn menu_control_padding() -> Padding {
|
pub fn menu_control_padding() -> Padding {
|
||||||
THEME
|
let guard = THEME.lock().unwrap();
|
||||||
.with(|t| {
|
let cosmic = guard.cosmic();
|
||||||
let t = t.borrow();
|
[cosmic.space_xxs(), cosmic.space_m()].into()
|
||||||
let cosmic = t.cosmic();
|
|
||||||
[cosmic.space_xxs(), cosmic.space_m()]
|
|
||||||
})
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,53 +6,60 @@
|
||||||
use cosmic_config::cosmic_config_derive::CosmicConfigEntry;
|
use cosmic_config::cosmic_config_derive::CosmicConfigEntry;
|
||||||
use cosmic_config::{Config, CosmicConfigEntry};
|
use cosmic_config::{Config, CosmicConfigEntry};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cell::RefCell;
|
use std::sync::{LazyLock, Mutex};
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/// ID for the `CosmicTk` config.
|
/// ID for the `CosmicTk` config.
|
||||||
pub const ID: &str = "com.system76.CosmicTk";
|
pub const ID: &str = "com.system76.CosmicTk";
|
||||||
|
|
||||||
thread_local! {
|
pub static COSMIC_TK: LazyLock<Mutex<CosmicTk>> = LazyLock::new(|| {
|
||||||
pub static COSMIC_TK: RefCell<CosmicTk> = RefCell::new(CosmicTk::config()
|
Mutex::new(
|
||||||
.map(|c| {
|
CosmicTk::config()
|
||||||
CosmicTk::get_entry(&c).unwrap_or_else(|(errors, mode)| {
|
.map(|c| {
|
||||||
for why in errors {
|
CosmicTk::get_entry(&c).unwrap_or_else(|(errors, mode)| {
|
||||||
tracing::error!(?why, "CosmicTk config entry error");
|
for why in errors {
|
||||||
}
|
tracing::error!(?why, "CosmicTk config entry error");
|
||||||
mode
|
}
|
||||||
})
|
mode
|
||||||
})
|
})
|
||||||
.unwrap_or_default())
|
})
|
||||||
}
|
.unwrap_or_default(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
/// Apply the theme to other toolkits.
|
/// Apply the theme to other toolkits.
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn apply_theme_global() -> bool {
|
pub fn apply_theme_global() -> bool {
|
||||||
COSMIC_TK.with(|tk| tk.borrow().apply_theme_global)
|
COSMIC_TK.lock().unwrap().apply_theme_global
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show minimize button in window header.
|
/// Show minimize button in window header.
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn show_minimize() -> bool {
|
pub fn show_minimize() -> bool {
|
||||||
COSMIC_TK.with(|tk| tk.borrow().show_minimize)
|
COSMIC_TK.lock().unwrap().show_minimize
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show maximize button in window header.
|
/// Show maximize button in window header.
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn show_maximize() -> bool {
|
pub fn show_maximize() -> bool {
|
||||||
COSMIC_TK.with(|tk| tk.borrow().show_maximize)
|
COSMIC_TK.lock().unwrap().show_maximize
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Preferred icon theme.
|
/// Preferred icon theme.
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn icon_theme() -> String {
|
pub fn icon_theme() -> String {
|
||||||
COSMIC_TK.with(|tk| tk.borrow().icon_theme.clone())
|
COSMIC_TK.lock().unwrap().icon_theme.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Density of CSD/SSD header bars.
|
/// Density of CSD/SSD header bars.
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn header_size() -> Density {
|
pub fn header_size() -> Density {
|
||||||
COSMIC_TK.with(|tk| tk.borrow().header_size)
|
COSMIC_TK.lock().unwrap().header_size
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interface density.
|
/// Interface density.
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn interface_density() -> Density {
|
pub fn interface_density() -> Density {
|
||||||
COSMIC_TK.with(|tk| tk.borrow().interface_density)
|
COSMIC_TK.lock().unwrap().interface_density
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, CosmicConfigEntry, Debug, Eq, PartialEq)]
|
#[derive(Clone, CosmicConfigEntry, Debug, Eq, PartialEq)]
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,21 @@
|
||||||
//! Select the preferred icon theme.
|
//! Select the preferred icon theme.
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
pub const COSMIC: &str = "Cosmic";
|
pub const COSMIC: &str = "Cosmic";
|
||||||
|
|
||||||
thread_local! {
|
pub(crate) static DEFAULT: Mutex<Cow<'static, str>> = Mutex::new(Cow::Borrowed(COSMIC));
|
||||||
/// The fallback icon theme to search if no icon theme was specified.
|
|
||||||
pub(crate) static DEFAULT: RefCell<Cow<'static, str>> = RefCell::new(COSMIC.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The fallback icon theme to search if no icon theme was specified.
|
/// The fallback icon theme to search if no icon theme was specified.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn default() -> String {
|
pub fn default() -> String {
|
||||||
DEFAULT.with(|theme| theme.borrow().to_string())
|
DEFAULT.lock().unwrap().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the fallback icon theme to search when loading system icons.
|
/// Set the fallback icon theme to search when loading system icons.
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn set_default(name: impl Into<Cow<'static, str>>) {
|
pub fn set_default(name: impl Into<Cow<'static, str>>) {
|
||||||
DEFAULT.with(|theme| *theme.borrow_mut() = name.into());
|
*DEFAULT.lock().unwrap() = name.into();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,7 @@ use cosmic_theme::Component;
|
||||||
use cosmic_theme::LayeredTheme;
|
use cosmic_theme::LayeredTheme;
|
||||||
use iced_futures::Subscription;
|
use iced_futures::Subscription;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[cfg(feature = "dbus-config")]
|
#[cfg(feature = "dbus-config")]
|
||||||
use cosmic_config::dbus;
|
use cosmic_config::dbus;
|
||||||
|
|
@ -46,18 +45,21 @@ lazy_static::lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local! {
|
pub(crate) static THEME: Mutex<Theme> = Mutex::new(Theme {
|
||||||
pub(crate) static THEME: RefCell<Theme> = RefCell::new(Theme { theme_type: ThemeType::Dark, layer: cosmic_theme::Layer::Background });
|
theme_type: ThemeType::Dark,
|
||||||
}
|
layer: cosmic_theme::Layer::Background,
|
||||||
|
});
|
||||||
|
|
||||||
/// Currently-defined theme.
|
/// Currently-defined theme.
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn active() -> Theme {
|
pub fn active() -> Theme {
|
||||||
THEME.with(|theme| theme.borrow().clone())
|
THEME.lock().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Currently-defined theme type.
|
/// Currently-defined theme type.
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn active_type() -> ThemeType {
|
pub fn active_type() -> ThemeType {
|
||||||
THEME.with(|theme| theme.borrow().theme_type.clone())
|
THEME.lock().unwrap().theme_type.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the active theme has a dark preference.
|
/// Whether the active theme has a dark preference.
|
||||||
|
|
|
||||||
|
|
@ -31,95 +31,85 @@ pub fn icon<'a, Message>(handle: impl Into<Handle>) -> Button<'a, Message> {
|
||||||
|
|
||||||
impl<'a, Message> Button<'a, Message> {
|
impl<'a, Message> Button<'a, Message> {
|
||||||
pub fn new(icon: Icon) -> Self {
|
pub fn new(icon: Icon) -> Self {
|
||||||
crate::theme::THEME.with(|theme_cell| {
|
let guard = crate::theme::THEME.lock().unwrap();
|
||||||
let theme = theme_cell.borrow();
|
let theme = guard.cosmic();
|
||||||
let theme = theme.cosmic();
|
let padding = theme.space_xxs();
|
||||||
let padding = theme.space_xxs();
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: Id::unique(),
|
id: Id::unique(),
|
||||||
label: Cow::Borrowed(""),
|
label: Cow::Borrowed(""),
|
||||||
tooltip: Cow::Borrowed(""),
|
tooltip: Cow::Borrowed(""),
|
||||||
on_press: None,
|
on_press: None,
|
||||||
width: Length::Shrink,
|
width: Length::Shrink,
|
||||||
height: Length::Shrink,
|
height: Length::Shrink,
|
||||||
padding: Padding::from(padding),
|
padding: Padding::from(padding),
|
||||||
spacing: theme.space_xxxs(),
|
spacing: theme.space_xxxs(),
|
||||||
icon_size: if icon.handle.symbolic { 16 } else { 24 },
|
icon_size: if icon.handle.symbolic { 16 } else { 24 },
|
||||||
line_height: 20,
|
line_height: 20,
|
||||||
font_size: 14,
|
font_size: 14,
|
||||||
font_weight: Weight::Normal,
|
font_weight: Weight::Normal,
|
||||||
style: Style::Icon,
|
style: Style::Icon,
|
||||||
variant: icon,
|
variant: icon,
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies the **Extra Small** button size preset.
|
/// Applies the **Extra Small** button size preset.
|
||||||
pub fn extra_small(mut self) -> Self {
|
pub fn extra_small(mut self) -> Self {
|
||||||
crate::theme::THEME.with(|theme_cell| {
|
let guard = crate::theme::THEME.lock().unwrap();
|
||||||
let theme = theme_cell.borrow();
|
let theme = guard.cosmic();
|
||||||
let theme = theme.cosmic();
|
|
||||||
|
|
||||||
self.font_size = 14;
|
self.font_size = 14;
|
||||||
self.font_weight = Weight::Normal;
|
self.font_weight = Weight::Normal;
|
||||||
self.icon_size = 16;
|
self.icon_size = 16;
|
||||||
self.line_height = 20;
|
self.line_height = 20;
|
||||||
self.padding = Padding::from(theme.space_xxs());
|
self.padding = Padding::from(theme.space_xxs());
|
||||||
self.spacing = theme.space_xxxs();
|
self.spacing = theme.space_xxxs();
|
||||||
});
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies the **Medium** button size preset.
|
/// Applies the **Medium** button size preset.
|
||||||
pub fn medium(mut self) -> Self {
|
pub fn medium(mut self) -> Self {
|
||||||
crate::theme::THEME.with(|theme_cell| {
|
let guard = crate::theme::THEME.lock().unwrap();
|
||||||
let theme = theme_cell.borrow();
|
let theme = guard.cosmic();
|
||||||
let theme = theme.cosmic();
|
|
||||||
|
|
||||||
self.font_size = 24;
|
self.font_size = 24;
|
||||||
self.font_weight = Weight::Normal;
|
self.font_weight = Weight::Normal;
|
||||||
self.icon_size = 32;
|
self.icon_size = 32;
|
||||||
self.line_height = 32;
|
self.line_height = 32;
|
||||||
self.padding = Padding::from(theme.space_xs());
|
self.padding = Padding::from(theme.space_xs());
|
||||||
self.spacing = theme.space_xxs();
|
self.spacing = theme.space_xxs();
|
||||||
});
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies the **Large** button size preset.
|
/// Applies the **Large** button size preset.
|
||||||
pub fn large(mut self) -> Self {
|
pub fn large(mut self) -> Self {
|
||||||
crate::theme::THEME.with(|theme_cell| {
|
let guard = crate::theme::THEME.lock().unwrap();
|
||||||
let theme = theme_cell.borrow();
|
let theme = guard.cosmic();
|
||||||
let theme = theme.cosmic();
|
|
||||||
|
|
||||||
self.font_size = 28;
|
self.font_size = 28;
|
||||||
self.font_weight = Weight::Normal;
|
self.font_weight = Weight::Normal;
|
||||||
self.icon_size = 40;
|
self.icon_size = 40;
|
||||||
self.line_height = 36;
|
self.line_height = 36;
|
||||||
self.padding = Padding::from(theme.space_xs());
|
self.padding = Padding::from(theme.space_xs());
|
||||||
self.spacing = theme.space_xxs();
|
self.spacing = theme.space_xxs();
|
||||||
});
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies the **Extra Large** button size preset.
|
/// Applies the **Extra Large** button size preset.
|
||||||
pub fn extra_large(mut self) -> Self {
|
pub fn extra_large(mut self) -> Self {
|
||||||
crate::theme::THEME.with(|theme_cell| {
|
let guard = crate::theme::THEME.lock().unwrap();
|
||||||
let theme = theme_cell.borrow();
|
let theme = guard.cosmic();
|
||||||
let theme = theme.cosmic();
|
let padding = theme.space_xs();
|
||||||
let padding = theme.space_xs();
|
|
||||||
|
|
||||||
self.font_size = 32;
|
self.font_size = 32;
|
||||||
self.font_weight = Weight::Light;
|
self.font_weight = Weight::Light;
|
||||||
self.icon_size = 56;
|
self.icon_size = 56;
|
||||||
self.line_height = 44;
|
self.line_height = 44;
|
||||||
self.padding = Padding::from(padding);
|
self.padding = Padding::from(padding);
|
||||||
self.spacing = theme.space_xxs();
|
self.spacing = theme.space_xxs();
|
||||||
});
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ pub struct Appearance {
|
||||||
impl Appearance {
|
impl Appearance {
|
||||||
// TODO: `Radius` is not `const fn` compatible.
|
// TODO: `Radius` is not `const fn` compatible.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let rad_0 = THEME.with(|t| t.borrow().cosmic().corner_radii.radius_0);
|
let rad_0 = THEME.lock().unwrap().cosmic().corner_radii.radius_0;
|
||||||
Self {
|
Self {
|
||||||
shadow_offset: Vector::new(0.0, 0.0),
|
shadow_offset: Vector::new(0.0, 0.0),
|
||||||
background: None,
|
background: None,
|
||||||
|
|
|
||||||
|
|
@ -51,26 +51,24 @@ impl Text {
|
||||||
|
|
||||||
impl<'a, Message> Button<'a, Message> {
|
impl<'a, Message> Button<'a, Message> {
|
||||||
pub fn new(text: Text) -> Self {
|
pub fn new(text: Text) -> Self {
|
||||||
crate::theme::THEME.with(|theme_cell| {
|
let guard = crate::theme::THEME.lock().unwrap();
|
||||||
let theme = theme_cell.borrow();
|
let theme = guard.cosmic();
|
||||||
let theme = theme.cosmic();
|
Self {
|
||||||
Self {
|
id: Id::unique(),
|
||||||
id: Id::unique(),
|
label: Cow::Borrowed(""),
|
||||||
label: Cow::Borrowed(""),
|
tooltip: Cow::Borrowed(""),
|
||||||
tooltip: Cow::Borrowed(""),
|
on_press: None,
|
||||||
on_press: None,
|
width: Length::Shrink,
|
||||||
width: Length::Shrink,
|
height: Length::Fixed(theme.space_l().into()),
|
||||||
height: Length::Fixed(theme.space_l().into()),
|
padding: Padding::from([0, theme.space_s()]),
|
||||||
padding: Padding::from([0, theme.space_s()]),
|
spacing: theme.space_xxxs(),
|
||||||
spacing: theme.space_xxxs(),
|
icon_size: 16,
|
||||||
icon_size: 16,
|
line_height: 20,
|
||||||
line_height: 20,
|
font_size: 14,
|
||||||
font_size: 14,
|
font_weight: Weight::Normal,
|
||||||
font_weight: Weight::Normal,
|
style: Style::Standard,
|
||||||
style: Style::Standard,
|
variant: text,
|
||||||
variant: text,
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn leading_icon(mut self, icon: impl Into<icon::Handle>) -> Self {
|
pub fn leading_icon(mut self, icon: impl Into<icon::Handle>) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -423,7 +423,7 @@ impl<'a, Message: 'a + Clone> Widget<Message, crate::Theme, crate::Renderer>
|
||||||
renderer.with_layer(parent_bounds, |renderer| {
|
renderer.with_layer(parent_bounds, |renderer| {
|
||||||
let selection_background = theme.selection_background();
|
let selection_background = theme.selection_background();
|
||||||
|
|
||||||
let c_rad = THEME.with(|t| t.borrow().cosmic().corner_radii);
|
let c_rad = THEME.lock().unwrap().cosmic().corner_radii;
|
||||||
|
|
||||||
// NOTE: Workaround to round the border of the unselected, unhovered image.
|
// NOTE: Workaround to round the border of the unselected, unhovered image.
|
||||||
if !self.selected && !is_mouse_over {
|
if !self.selected && !is_mouse_over {
|
||||||
|
|
|
||||||
|
|
@ -177,11 +177,7 @@ fn padded_control<'a, Message>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn menu_control_padding() -> Padding {
|
fn menu_control_padding() -> Padding {
|
||||||
crate::theme::THEME
|
let guard = crate::theme::THEME.lock().unwrap();
|
||||||
.with(|t| {
|
let cosmic = guard.cosmic();
|
||||||
let t = t.borrow();
|
[cosmic.space_xxs(), cosmic.space_m()].into()
|
||||||
let cosmic = t.cosmic();
|
|
||||||
[cosmic.space_xxs(), cosmic.space_m()]
|
|
||||||
})
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,7 @@ where
|
||||||
copied_to_clipboard_label: T,
|
copied_to_clipboard_label: T,
|
||||||
) -> ColorPicker<'a, Message> {
|
) -> ColorPicker<'a, Message> {
|
||||||
let on_update = self.on_update;
|
let on_update = self.on_update;
|
||||||
let spacing = THEME.with(|t| t.borrow().cosmic().spacing);
|
let spacing = THEME.lock().unwrap().cosmic().spacing;
|
||||||
let mut inner = column![
|
let mut inner = column![
|
||||||
// segmented buttons
|
// segmented buttons
|
||||||
segmented_control::horizontal(self.model)
|
segmented_control::horizontal(self.model)
|
||||||
|
|
@ -595,7 +595,7 @@ where
|
||||||
let bounds = canvas_layout.bounds();
|
let bounds = canvas_layout.bounds();
|
||||||
// Draw the handle on the saturation value canvas
|
// Draw the handle on the saturation value canvas
|
||||||
|
|
||||||
let t = THEME.with(|t| t.borrow().clone());
|
let t = THEME.lock().unwrap().clone();
|
||||||
let t = t.cosmic();
|
let t = t.cosmic();
|
||||||
let handle_radius = f32::from(t.space_xs()) / 2.0;
|
let handle_radius = f32::from(t.space_xs()) / 2.0;
|
||||||
let (x, y) = (
|
let (x, y) = (
|
||||||
|
|
@ -779,7 +779,7 @@ pub fn color_button<'a, Message: 'static>(
|
||||||
color: Option<Color>,
|
color: Option<Color>,
|
||||||
icon_portion: Length,
|
icon_portion: Length,
|
||||||
) -> crate::widget::Button<'a, Message> {
|
) -> crate::widget::Button<'a, Message> {
|
||||||
let spacing = THEME.with(|t| t.borrow().cosmic().spacing);
|
let spacing = THEME.lock().unwrap().cosmic().spacing;
|
||||||
|
|
||||||
button(if color.is_some() {
|
button(if color.is_some() {
|
||||||
Element::from(vertical_space(Length::Fixed(f32::from(spacing.space_s))))
|
Element::from(vertical_space(Length::Fixed(f32::from(spacing.space_s))))
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,7 @@ impl<'a, Message: Clone + 'static> From<Dialog<'a, Message>> for Element<'a, Mes
|
||||||
space_s,
|
space_s,
|
||||||
space_xxs,
|
space_xxs,
|
||||||
..
|
..
|
||||||
} = theme::THEME.with(|theme_cell| {
|
} = theme::THEME.lock().unwrap().cosmic().spacing;
|
||||||
let theme = theme_cell.borrow();
|
|
||||||
let theme = theme.cosmic();
|
|
||||||
theme.spacing
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut content_col = widget::column::with_capacity(3 + dialog.controls.len() * 2);
|
let mut content_col = widget::column::with_capacity(3 + dialog.controls.len() * 2);
|
||||||
content_col = content_col.push(widget::text::title3(dialog.title));
|
content_col = content_col.push(widget::text::title3(dialog.title));
|
||||||
|
|
|
||||||
|
|
@ -75,38 +75,35 @@ impl Named {
|
||||||
lookup.find()
|
lookup.find()
|
||||||
};
|
};
|
||||||
|
|
||||||
crate::icon_theme::DEFAULT.with(|theme| {
|
let theme = crate::icon_theme::DEFAULT.lock().unwrap();
|
||||||
let theme = theme.borrow();
|
let themes = if theme.as_ref() == crate::icon_theme::COSMIC {
|
||||||
|
vec![theme.as_ref()]
|
||||||
|
} else {
|
||||||
|
vec![theme.as_ref(), crate::icon_theme::COSMIC]
|
||||||
|
};
|
||||||
|
|
||||||
let themes = if theme.as_ref() == crate::icon_theme::COSMIC {
|
let mut result = themes.iter().find_map(|t| locate(t, name));
|
||||||
vec![theme.as_ref()]
|
|
||||||
} else {
|
|
||||||
vec![theme.as_ref(), crate::icon_theme::COSMIC]
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut result = themes.iter().find_map(|t| locate(t, name));
|
// On failure, attempt to locate fallback icon.
|
||||||
|
if result.is_none() {
|
||||||
// On failure, attempt to locate fallback icon.
|
if matches!(fallback, Some(IconFallback::Default)) {
|
||||||
if result.is_none() {
|
for new_name in name.rmatch_indices('-').map(|(pos, _)| &name[..pos]) {
|
||||||
if matches!(fallback, Some(IconFallback::Default)) {
|
result = themes.iter().find_map(|t| locate(t, new_name));
|
||||||
for new_name in name.rmatch_indices('-').map(|(pos, _)| &name[..pos]) {
|
if result.is_some() {
|
||||||
result = themes.iter().find_map(|t| locate(t, new_name));
|
break;
|
||||||
if result.is_some() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if let Some(IconFallback::Names(fallbacks)) = fallback {
|
}
|
||||||
for fallback in fallbacks {
|
} else if let Some(IconFallback::Names(fallbacks)) = fallback {
|
||||||
result = themes.iter().find_map(|t| locate(t, fallback));
|
for fallback in fallbacks {
|
||||||
if result.is_some() {
|
result = themes.iter().find_map(|t| locate(t, fallback));
|
||||||
break;
|
if result.is_some() {
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
|
|
||||||
|
|
@ -1361,7 +1361,7 @@ where
|
||||||
bounds.y = bounds.y + bounds.height - width;
|
bounds.y = bounds.y + bounds.height - width;
|
||||||
bounds.height = width;
|
bounds.height = width;
|
||||||
|
|
||||||
let rad_0 = THEME.with(|t| t.borrow().cosmic().corner_radii.radius_0);
|
let rad_0 = THEME.lock().unwrap().cosmic().corner_radii.radius_0;
|
||||||
renderer.fill_quad(
|
renderer.fill_quad(
|
||||||
renderer::Quad {
|
renderer::Quad {
|
||||||
bounds,
|
bounds,
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ pub fn search_input<'a, Message>(
|
||||||
where
|
where
|
||||||
Message: Clone + 'static,
|
Message: Clone + 'static,
|
||||||
{
|
{
|
||||||
let spacing = THEME.with(|t| t.borrow().cosmic().space_xxs());
|
let spacing = THEME.lock().unwrap().cosmic().space_xxs();
|
||||||
|
|
||||||
TextInput::new(placeholder, value)
|
TextInput::new(placeholder, value)
|
||||||
.padding([0, spacing, 0, spacing])
|
.padding([0, spacing, 0, spacing])
|
||||||
|
|
@ -117,7 +117,7 @@ pub fn secure_input<'a, Message>(
|
||||||
where
|
where
|
||||||
Message: Clone + 'static,
|
Message: Clone + 'static,
|
||||||
{
|
{
|
||||||
let spacing = THEME.with(|t| t.borrow().cosmic().space_xxs());
|
let spacing = THEME.lock().unwrap().cosmic().space_xxs();
|
||||||
let mut input = TextInput::new(placeholder, value)
|
let mut input = TextInput::new(placeholder, value)
|
||||||
.padding([0, spacing, 0, spacing])
|
.padding([0, spacing, 0, spacing])
|
||||||
.style(crate::theme::TextInput::Default)
|
.style(crate::theme::TextInput::Default)
|
||||||
|
|
@ -156,7 +156,7 @@ pub fn inline_input<'a, Message>(
|
||||||
where
|
where
|
||||||
Message: Clone + 'static,
|
Message: Clone + 'static,
|
||||||
{
|
{
|
||||||
let spacing = THEME.with(|t| t.borrow().cosmic().space_xxs());
|
let spacing = THEME.lock().unwrap().cosmic().space_xxs();
|
||||||
|
|
||||||
TextInput::new(placeholder, value)
|
TextInput::new(placeholder, value)
|
||||||
.style(crate::theme::TextInput::Inline)
|
.style(crate::theme::TextInput::Inline)
|
||||||
|
|
@ -223,7 +223,7 @@ where
|
||||||
/// - a placeholder,
|
/// - a placeholder,
|
||||||
/// - the current value
|
/// - the current value
|
||||||
pub fn new(placeholder: impl Into<Cow<'a, str>>, value: impl Into<Cow<'a, str>>) -> Self {
|
pub fn new(placeholder: impl Into<Cow<'a, str>>, value: impl Into<Cow<'a, str>>) -> Self {
|
||||||
let spacing = THEME.with(|t| t.borrow().cosmic().space_xxs());
|
let spacing = THEME.lock().unwrap().cosmic().space_xxs();
|
||||||
|
|
||||||
let v: Cow<'a, str> = value.into();
|
let v: Cow<'a, str> = value.into();
|
||||||
TextInput {
|
TextInput {
|
||||||
|
|
@ -486,7 +486,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_clear(self, on_clear: Message) -> Self {
|
pub fn on_clear(self, on_clear: Message) -> Self {
|
||||||
let spacing = THEME.with(|t| t.borrow().cosmic().space_xxs());
|
let spacing = THEME.lock().unwrap().cosmic().space_xxs();
|
||||||
|
|
||||||
self.trailing_icon(
|
self.trailing_icon(
|
||||||
crate::widget::icon::from_name("edit-clear-symbolic")
|
crate::widget::icon::from_name("edit-clear-symbolic")
|
||||||
|
|
@ -992,7 +992,7 @@ pub fn layout<Message>(
|
||||||
tree: &mut Tree,
|
tree: &mut Tree,
|
||||||
) -> layout::Node {
|
) -> layout::Node {
|
||||||
let limits = limits.width(width);
|
let limits = limits.width(width);
|
||||||
let spacing = THEME.with(|t| t.borrow().cosmic().space_xxs());
|
let spacing = THEME.lock().unwrap().cosmic().space_xxs();
|
||||||
let mut nodes = Vec::with_capacity(3);
|
let mut nodes = Vec::with_capacity(3);
|
||||||
|
|
||||||
let text_pos = if let Some(label) = label {
|
let text_pos = if let Some(label) = label {
|
||||||
|
|
@ -2186,9 +2186,7 @@ pub fn draw<'a, Message>(
|
||||||
let font = font.unwrap_or_else(|| renderer.default_font());
|
let font = font.unwrap_or_else(|| renderer.default_font());
|
||||||
let size = size.unwrap_or_else(|| renderer.default_size().0);
|
let size = size.unwrap_or_else(|| renderer.default_size().0);
|
||||||
|
|
||||||
let radius_0 = THEME
|
let radius_0 = THEME.lock().unwrap().cosmic().corner_radii.radius_0.into();
|
||||||
.with(|t| t.borrow().cosmic().corner_radii.radius_0)
|
|
||||||
.into();
|
|
||||||
let (cursor, offset) = if let Some(focus) = &state.is_focused {
|
let (cursor, offset) = if let Some(focus) = &state.is_focused {
|
||||||
match state.cursor.state(value) {
|
match state.cursor.state(value) {
|
||||||
cursor::State::Index(position) => {
|
cursor::State::Index(position) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue