WIP: libscosmic reskin
This commit is contained in:
parent
487b7b299d
commit
3bfc65d634
13 changed files with 326 additions and 254 deletions
|
|
@ -1 +1 @@
|
||||||
Dark((name:"cosmic-dark",bright_red:(red:1.0,green:0.62745098,blue:0.60392157,alpha:1.0),bright_green:(red:0.36862745,green:0.85882352,blue:0.54901960,alpha:1.0),bright_orange:(red:1.0,green:0.63921569,blue:0.49019608,alpha:1.0),gray_1:(red:0.10588235,green:0.10588235,blue:0.10588235,alpha:1.0),gray_2:(red:0.14901961,green:0.14901961,blue:0.14901961,alpha:1.0),neutral_0:(red:0.0,green:0.0,blue:0.0,alpha:1.0),neutral_1:(red:0.01176471,green:0.01176471,blue:0.01176471,alpha:1.0),neutral_2:(red:0.08627451,green:0.08627451,blue:0.08627451,alpha:1.0),neutral_3:(red:0.18039216,green:0.18039216,blue:0.18039216,alpha:1.0),neutral_4:(red:0.28235294,green:0.28235294,blue:0.28235294,alpha:1.0),neutral_5:(red:0.38823529,green:0.38823529,blue:0.38823529,alpha:1.0),neutral_6:(red:0.50196078,green:0.50196078,blue:0.50196078,alpha:1.0),neutral_7:(red:0.61960784,green:0.61960784,blue:0.61960784,alpha:1.0),neutral_8:(red:0.74509804,green:0.74509804,blue:0.74509804,alpha:1.0),neutral_9:(red:0.87058824,green:0.87058824,blue:0.87058824,alpha:1.0),neutral_10:(red:1.0,green:1.0,blue:1.0,alpha:1.0),accent_blue:(red:0.3882353,green:0.81568627,blue:0.87450981,alpha:1.0),accent_indigo:(red:0.63137255,green:0.75294118,blue:0.92156863,alpha:1.0),accent_purple:(red:0.90588235,green:0.61176471,blue:0.99607843,alpha:1.0),accent_pink:(red:1.0,green:0.61176471,blue:0.69411765,alpha:1.0),accent_red:(red:0.99215686,green:0.63137255,blue:0.62745098,alpha:1.0),accent_orange:(red:1.0,green:0.67843137,blue:0.0,alpha:1.0),accent_yellow:(red:0.96862745,green:0.87843137,blue:0.38431373,alpha:1.0),accent_green:(red:0.57254902,green:0.81176471,blue:0.61176471,alpha:1.0),accent_warm_grey:(red:0.79215686,green:0.72941176,blue:0.70588235,alpha:1.0),ext_warm_grey:(red:0.60784314,green:0.55686275,blue:0.54117647,alpha:1.0),ext_orange:(red:1.0,green:0.67843137,blue:0.0,alpha:1.0),ext_yellow:(red:0.99607843,green:0.85882353,blue:0.25098039,alpha:1.0),ext_blue:(red:0.28235294,green:0.72549020,blue:0.78039216,alpha:1.0),ext_purple:(red:0.81176471,green:0.49019608,blue:1.0,alpha:1.0),ext_pink:(red:0.97647059,green:0.22745098,blue:0.51372549,alpha:1.0),ext_indigo:(red:0.24313725,green:0.53333333,blue:1.0,alpha:1.0)))
|
Dark((name:"cosmic-dark",bright_red:(red:1.0,green:0.62745098,blue:0.60392157,alpha:1.0),bright_green:(red:0.36862745,green:0.85882352,blue:0.54901960,alpha:1.0),bright_orange:(red:1.0,green:0.63921569,blue:0.49019608,alpha:1.0),gray_1:(red:0.10588235,green:0.10588235,blue:0.10588235,alpha:1.0),gray_2:(red:0.14901961,green:0.14901961,blue:0.14901961,alpha:1.0),neutral_0:(red:0.0,green:0.0,blue:0.0,alpha:1.0),neutral_1:(red:0.01176471,green:0.01176471,blue:0.01176471,alpha:1.0),neutral_2:(red:0.08627451,green:0.08627451,blue:0.08627451,alpha:1.0),neutral_3:(red:0.18039216,green:0.18039216,blue:0.18039216,alpha:1.0),neutral_4:(red:0.28235294,green:0.28235294,blue:0.28235294,alpha:1.0),neutral_5:(red:0.38823529,green:0.38823529,blue:0.38823529,alpha:1.0),neutral_6:(red:0.50196078,green:0.50196078,blue:0.50196078,alpha:1.0),neutral_7:(red:0.61960784,green:0.61960784,blue:0.61960784,alpha:1.0),neutral_8:(red:0.74509804,green:0.74509804,blue:0.74509804,alpha:1.0),neutral_9:(red:0.87058824,green:0.87058824,blue:0.87058824,alpha:1.0),neutral_10:(red:1.0,green:1.0,blue:1.0,alpha:1.0),accent_blue:(red:0.0,green:0.58823529,blue:0.53333333,alpha:1.0),accent_indigo:(red:0.63137255,green:0.75294118,blue:0.92156863,alpha:1.0),accent_purple:(red:0.90588235,green:0.61176471,blue:0.99607843,alpha:1.0),accent_pink:(red:1.0,green:0.61176471,blue:0.69411765,alpha:1.0),accent_red:(red:0.99215686,green:0.63137255,blue:0.62745098,alpha:1.0),accent_orange:(red:1.0,green:0.67843137,blue:0.0,alpha:1.0),accent_yellow:(red:0.96862745,green:0.87843137,blue:0.38431373,alpha:1.0),accent_green:(red:0.57254902,green:0.81176471,blue:0.61176471,alpha:1.0),accent_warm_grey:(red:0.79215686,green:0.72941176,blue:0.70588235,alpha:1.0),ext_warm_grey:(red:0.60784314,green:0.55686275,blue:0.54117647,alpha:1.0),ext_orange:(red:1.0,green:0.67843137,blue:0.0,alpha:1.0),ext_yellow:(red:0.99607843,green:0.85882353,blue:0.25098039,alpha:1.0),ext_blue:(red:0.28235294,green:0.72549020,blue:0.78039216,alpha:1.0),ext_purple:(red:0.81176471,green:0.49019608,blue:1.0,alpha:1.0),ext_pink:(red:0.97647059,green:0.22745098,blue:0.51372549,alpha:1.0),ext_indigo:(red:0.24313725,green:0.53333333,blue:1.0,alpha:1.0)))
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Light((name:"cosmic-light",bright_red:(red:0.53725490,green:0.01568627,blue:0.09411765,alpha:1.0),bright_green:(red:0.0,green:0.34117647,blue:0.17254901,alpha:1.0),bright_orange:(red:0.47450980,green:0.17254902,blue:0.0,alpha:1.0),gray_1:(red:0.84313725,green:0.84313725,blue:0.84313725,alpha:1.0),gray_2:(red:0.89411765,green:0.89411765,blue:0.89411765,alpha:1.0),neutral_0:(red:1.0,green:1.0,blue:1.0,alpha:1.0),neutral_1:(red:0.87058824,green:0.87058824,blue:0.87058824,alpha:1.0),neutral_2:(red:0.74509804,green:0.74509804,blue:0.74509804,alpha:1.0),neutral_3:(red:0.61960784,green:0.61960784,blue:0.61960784,alpha:1.0),neutral_4:(red:0.50196078,green:0.50196078,blue:0.50196078,alpha:1.0),neutral_5:(red:0.38823529,green:0.38823529,blue:0.38823529,alpha:1.0),neutral_6:(red:0.28235294,green:0.28235294,blue:0.28235294,alpha:1.0),neutral_7:(red:0.18039216,green:0.18039216,blue:0.18039216,alpha:1.0),neutral_8:(red:0.08627451,green:0.08627451,blue:0.08627451,alpha:1.0),neutral_9:(red:0.01176471,green:0.01176471,blue:0.01176471,alpha:1.0),neutral_10:(red:0.0,green:0.0,blue:0.0,alpha:1.0),accent_blue:(red:0.0,green:0.32156863,blue:0.35294118,alpha:1.0),accent_indigo:(red:0.18039216,green:0.28627451,blue:0.42745098,alpha:1.0),accent_purple:(red:0.40784314,green:0.12941176,blue:0.48627451,alpha:1.0),accent_pink:(red:0.52549020,green:0.01568627,blue:0.22745098,alpha:1.0),accent_red:(red:0.47058824,green:0.16078431,blue:0.18039216,alpha:1.0),accent_orange:(red:0.38431373,green:0.25098039,blue:0.0,alpha:1.0),accent_yellow:(red:0.32549020,green:0.28235294,blue:0.0,alpha:1.0),accent_green:(red:0.09411765,green:0.33333333,blue:0.16078431,alpha:1.0),accent_warm_grey:(red:0.33333333,green:0.27843137,blue:0.25882353,alpha:1.0),ext_warm_grey:(red:0.60784314,green:0.55686275,blue:0.54117647,alpha:1.0),ext_orange:(red:0.98431373,green:0.72156863,blue:0.42352941,alpha:1.0),ext_yellow:(red:0.96862745,green:0.87843137,blue:0.38431373,alpha:1.0),ext_blue:(red:0.41568627,green:0.79215686,blue:0.84705882,alpha:1.0),ext_purple:(red:0.83529412,green:0.54901961,blue:1.0,alpha:1.0),ext_pink:(red:1.0,green:0.61176471,blue:0.86666667,alpha:1.0),ext_indigo:(red:0.58431373,green:0.76862745,blue:0.98823529,alpha:1.0)))
|
Light((name:"cosmic-light",bright_red:(red:0.53725490,green:0.01568627,blue:0.09411765,alpha:1.0),bright_green:(red:0.0,green:0.34117647,blue:0.17254901,alpha:1.0),bright_orange:(red:0.47450980,green:0.17254902,blue:0.0,alpha:1.0),gray_1:(red:0.84313725,green:0.84313725,blue:0.84313725,alpha:1.0),gray_2:(red:0.89411765,green:0.89411765,blue:0.89411765,alpha:1.0),neutral_0:(red:1.0,green:1.0,blue:1.0,alpha:1.0),neutral_1:(red:0.87058824,green:0.87058824,blue:0.87058824,alpha:1.0),neutral_2:(red:0.74509804,green:0.74509804,blue:0.74509804,alpha:1.0),neutral_3:(red:0.61960784,green:0.61960784,blue:0.61960784,alpha:1.0),neutral_4:(red:0.50196078,green:0.50196078,blue:0.50196078,alpha:1.0),neutral_5:(red:0.38823529,green:0.38823529,blue:0.38823529,alpha:1.0),neutral_6:(red:0.28235294,green:0.28235294,blue:0.28235294,alpha:1.0),neutral_7:(red:0.18039216,green:0.18039216,blue:0.18039216,alpha:1.0),neutral_8:(red:0.08627451,green:0.08627451,blue:0.08627451,alpha:1.0),neutral_9:(red:0.01176471,green:0.01176471,blue:0.01176471,alpha:1.0),neutral_10:(red:0.0,green:0.0,blue:0.0,alpha:1.0),accent_blue:(red:0.0,green:0.58823529,blue:0.53333333,alpha:1.0),accent_indigo:(red:0.18039216,green:0.28627451,blue:0.42745098,alpha:1.0),accent_purple:(red:0.40784314,green:0.12941176,blue:0.48627451,alpha:1.0),accent_pink:(red:0.52549020,green:0.01568627,blue:0.22745098,alpha:1.0),accent_red:(red:0.47058824,green:0.16078431,blue:0.18039216,alpha:1.0),accent_orange:(red:0.38431373,green:0.25098039,blue:0.0,alpha:1.0),accent_yellow:(red:0.32549020,green:0.28235294,blue:0.0,alpha:1.0),accent_green:(red:0.09411765,green:0.33333333,blue:0.16078431,alpha:1.0),accent_warm_grey:(red:0.33333333,green:0.27843137,blue:0.25882353,alpha:1.0),ext_warm_grey:(red:0.60784314,green:0.55686275,blue:0.54117647,alpha:1.0),ext_orange:(red:0.98431373,green:0.72156863,blue:0.42352941,alpha:1.0),ext_yellow:(red:0.96862745,green:0.87843137,blue:0.38431373,alpha:1.0),ext_blue:(red:0.41568627,green:0.79215686,blue:0.84705882,alpha:1.0),ext_purple:(red:0.83529412,green:0.54901961,blue:1.0,alpha:1.0),ext_pink:(red:1.0,green:0.61176471,blue:0.86666667,alpha:1.0),ext_indigo:(red:0.58431373,green:0.76862745,blue:0.98823529,alpha:1.0)))
|
||||||
|
|
|
||||||
|
|
@ -145,9 +145,14 @@ impl Theme {
|
||||||
/// This produces a clean, minimal light theme with pure white backgrounds,
|
/// This produces a clean, minimal light theme with pure white backgrounds,
|
||||||
/// generous window rounding, and subtle gray surfaces.
|
/// generous window rounding, and subtle gray surfaces.
|
||||||
pub fn light_default() -> Self {
|
pub fn light_default() -> Self {
|
||||||
|
// stateDefault: rgb(0, 150, 136)
|
||||||
|
let state_default = Srgb::new(0.0, 150.0 / 255.0, 136.0 / 255.0);
|
||||||
|
|
||||||
let mut builder = ThemeBuilder::light()
|
let mut builder = ThemeBuilder::light()
|
||||||
.bg_color(Srgba::new(1.0, 1.0, 1.0, 1.0))
|
.bg_color(Srgba::new(1.0, 1.0, 1.0, 1.0))
|
||||||
.primary_container_bg(Srgba::new(0.96, 0.96, 0.96, 1.0))
|
.primary_container_bg(Srgba::new(0.96, 0.96, 0.96, 1.0))
|
||||||
|
.accent(state_default)
|
||||||
|
.text_tint(Srgb::new(0.0, 0.0, 0.0))
|
||||||
.corner_radii(CornerRadii {
|
.corner_radii(CornerRadii {
|
||||||
radius_window: [16.0; 4],
|
radius_window: [16.0; 4],
|
||||||
..CornerRadii::default()
|
..CornerRadii::default()
|
||||||
|
|
@ -159,7 +164,10 @@ impl Theme {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// get the built in dark theme
|
/// get the built in dark theme
|
||||||
pub fn dark_default() -> Self {
|
pub fn dark_default() -> Self {
|
||||||
DARK_PALETTE.clone().into()
|
let state_default = Srgb::new(0.0, 150.0 / 255.0, 136.0 / 255.0);
|
||||||
|
ThemeBuilder::dark()
|
||||||
|
.accent(state_default)
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -1358,6 +1366,26 @@ impl ThemeBuilder {
|
||||||
};
|
};
|
||||||
theme.spacing = spacing;
|
theme.spacing = spacing;
|
||||||
theme.corner_radii = corner_radii;
|
theme.corner_radii = corner_radii;
|
||||||
|
|
||||||
|
// Force white container/component backgrounds for light themes
|
||||||
|
// to eliminate any brownish derived tint from color stepping.
|
||||||
|
if !is_dark {
|
||||||
|
let white = Srgba::new(1.0, 1.0, 1.0, 1.0);
|
||||||
|
let light_gray = Srgba::new(0.96, 0.96, 0.96, 1.0);
|
||||||
|
|
||||||
|
// Background container: pure white base, white component
|
||||||
|
theme.background.base = white;
|
||||||
|
theme.background.component.base = white;
|
||||||
|
|
||||||
|
// Primary container: very light gray base, white component
|
||||||
|
theme.primary.base = light_gray;
|
||||||
|
theme.primary.component.base = white;
|
||||||
|
|
||||||
|
// Secondary container: light gray base, white component
|
||||||
|
theme.secondary.base = Srgba::new(0.93, 0.93, 0.93, 1.0);
|
||||||
|
theme.secondary.component.base = white;
|
||||||
|
}
|
||||||
|
|
||||||
theme
|
theme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -747,10 +747,11 @@ impl<T: Application> Cosmic<T> {
|
||||||
self.app.core_mut().theme_sub_counter += 1;
|
self.app.core_mut().theme_sub_counter += 1;
|
||||||
|
|
||||||
let portal_accent = self.app.core().portal_accent;
|
let portal_accent = self.app.core().portal_accent;
|
||||||
if let Some(a) = portal_accent {
|
if let Some(_a) = portal_accent {
|
||||||
let t_inner = theme.cosmic();
|
let t_inner = theme.cosmic();
|
||||||
if a.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
let state_default = crate::theme::STATE_DEFAULT_ACCENT;
|
||||||
theme = Theme::system(Arc::new(t_inner.with_accent(a)));
|
if state_default.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
||||||
|
theme = Theme::system(Arc::new(t_inner.with_accent(state_default)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -777,15 +778,14 @@ impl<T: Application> Cosmic<T> {
|
||||||
prefer_dark,
|
prefer_dark,
|
||||||
} = cosmic_theme.theme_type
|
} = cosmic_theme.theme_type
|
||||||
{
|
{
|
||||||
let mut new_theme = if let Some(a) = portal_accent {
|
let state_default = crate::theme::STATE_DEFAULT_ACCENT;
|
||||||
|
let mut new_theme = {
|
||||||
let t_inner = theme.cosmic();
|
let t_inner = theme.cosmic();
|
||||||
if a.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
if state_default.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
||||||
Theme::system(Arc::new(t_inner.with_accent(a)))
|
Theme::system(Arc::new(t_inner.with_accent(state_default)))
|
||||||
} else {
|
} else {
|
||||||
theme
|
theme
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
theme
|
|
||||||
};
|
};
|
||||||
new_theme.theme_type.prefer_dark(prefer_dark);
|
new_theme.theme_type.prefer_dark(prefer_dark);
|
||||||
|
|
||||||
|
|
@ -918,15 +918,14 @@ impl<T: Application> Cosmic<T> {
|
||||||
cmds.push(self.app.system_theme_update(&[], new_theme.cosmic()));
|
cmds.push(self.app.system_theme_update(&[], new_theme.cosmic()));
|
||||||
|
|
||||||
let core = self.app.core_mut();
|
let core = self.app.core_mut();
|
||||||
new_theme = if let Some(a) = core.portal_accent {
|
new_theme = {
|
||||||
|
let state_default = crate::theme::STATE_DEFAULT_ACCENT;
|
||||||
let t_inner = new_theme.cosmic();
|
let t_inner = new_theme.cosmic();
|
||||||
if a.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
if state_default.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
||||||
Theme::system(Arc::new(t_inner.with_accent(a)))
|
Theme::system(Arc::new(t_inner.with_accent(state_default)))
|
||||||
} else {
|
} else {
|
||||||
new_theme
|
new_theme
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
new_theme
|
|
||||||
};
|
};
|
||||||
|
|
||||||
core.system_theme = new_theme.clone();
|
core.system_theme = new_theme.clone();
|
||||||
|
|
@ -1120,13 +1119,12 @@ impl<T: Application> Cosmic<T> {
|
||||||
}
|
}
|
||||||
#[cfg(feature = "xdg-portal")]
|
#[cfg(feature = "xdg-portal")]
|
||||||
Action::DesktopSettings(crate::theme::portal::Desktop::Accent(c)) => {
|
Action::DesktopSettings(crate::theme::portal::Desktop::Accent(c)) => {
|
||||||
use palette::Srgba;
|
let state_default = crate::theme::STATE_DEFAULT_ACCENT;
|
||||||
let c = Srgba::new(c.red() as f32, c.green() as f32, c.blue() as f32, 1.0);
|
|
||||||
let core = self.app.core_mut();
|
let core = self.app.core_mut();
|
||||||
core.portal_accent = Some(c);
|
core.portal_accent = Some(state_default);
|
||||||
let cur_accent = core.system_theme.cosmic().accent_color();
|
let cur_accent = core.system_theme.cosmic().accent_color();
|
||||||
|
|
||||||
if cur_accent.distance_squared(*c) < 0.00001 {
|
if cur_accent.distance_squared(*state_default) < 0.00001 {
|
||||||
// skip calculations if we already have the same color
|
// skip calculations if we already have the same color
|
||||||
return iced::Task::none();
|
return iced::Task::none();
|
||||||
}
|
}
|
||||||
|
|
@ -1141,7 +1139,7 @@ impl<T: Application> Cosmic<T> {
|
||||||
} = cosmic_theme.theme_type.clone()
|
} = cosmic_theme.theme_type.clone()
|
||||||
{
|
{
|
||||||
cosmic_theme.set_theme(ThemeType::System {
|
cosmic_theme.set_theme(ThemeType::System {
|
||||||
theme: Arc::new(t.with_accent(c)),
|
theme: Arc::new(t.with_accent(state_default)),
|
||||||
prefer_dark,
|
prefer_dark,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -563,22 +563,12 @@ impl<App: Application> ApplicationExt for App {
|
||||||
let maximized = core.window.is_maximized;
|
let maximized = core.window.is_maximized;
|
||||||
let content_container = core.window.content_container;
|
let content_container = core.window.content_container;
|
||||||
let show_context = core.window.show_context;
|
let show_context = core.window.show_context;
|
||||||
let nav_bar_active = core.nav_bar_active();
|
|
||||||
let focused = core
|
let focused = core
|
||||||
.focus_chain()
|
.focus_chain()
|
||||||
.iter()
|
.iter()
|
||||||
.any(|i| Some(*i) == self.core().main_window_id());
|
.any(|i| Some(*i) == self.core().main_window_id());
|
||||||
|
|
||||||
let border_padding = if maximized { 8 } else { 7 };
|
let main_content_padding = [0, 0, 0, 0];
|
||||||
|
|
||||||
let main_content_padding = if !content_container {
|
|
||||||
[0, 0, 0, 0]
|
|
||||||
} else {
|
|
||||||
let right_padding = if show_context { 0 } else { border_padding };
|
|
||||||
let left_padding = if nav_bar_active { 0 } else { border_padding };
|
|
||||||
|
|
||||||
[0, right_padding, 0, left_padding]
|
|
||||||
};
|
|
||||||
|
|
||||||
let content_row = crate::widget::row::with_children({
|
let content_row = crate::widget::row::with_children({
|
||||||
let mut widgets = Vec::with_capacity(3);
|
let mut widgets = Vec::with_capacity(3);
|
||||||
|
|
@ -590,14 +580,27 @@ impl<App: Application> ApplicationExt for App {
|
||||||
{
|
{
|
||||||
widgets.push(
|
widgets.push(
|
||||||
container(nav)
|
container(nav)
|
||||||
.padding([
|
.padding([0, 0, 0, 0])
|
||||||
0,
|
|
||||||
if is_condensed { border_padding } else { 8 },
|
|
||||||
border_padding,
|
|
||||||
border_padding,
|
|
||||||
])
|
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Vertical divider between nav bar and content
|
||||||
|
{
|
||||||
|
use iced::widget::{vertical_rule, rule};
|
||||||
|
widgets.push(
|
||||||
|
vertical_rule(1)
|
||||||
|
.class(crate::theme::Rule::Custom(Box::new(
|
||||||
|
|_: &crate::Theme| rule::Style {
|
||||||
|
color: iced_core::Color::from_rgba8(224, 224, 224, 1.0),
|
||||||
|
width: 1,
|
||||||
|
radius: 0.0.into(),
|
||||||
|
fill_mode: rule::FillMode::Full,
|
||||||
|
},
|
||||||
|
)))
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
|
@ -628,7 +631,7 @@ impl<App: Application> ApplicationExt for App {
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.apply(container)
|
.apply(container)
|
||||||
.padding([0, if content_container { border_padding } else { 0 }, 0, 0])
|
.padding([0, 0, 0, 0])
|
||||||
.apply(Element::from)
|
.apply(Element::from)
|
||||||
.map(crate::Action::App),
|
.map(crate::Action::App),
|
||||||
);
|
);
|
||||||
|
|
@ -668,13 +671,9 @@ impl<App: Application> ApplicationExt for App {
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.apply(container)
|
.apply(container)
|
||||||
.padding(if content_container {
|
.padding([0, 0, 0, 0])
|
||||||
[0, border_padding, border_padding, border_padding]
|
|
||||||
} else {
|
|
||||||
[0, 0, 0, 0]
|
|
||||||
})
|
|
||||||
.into(),
|
.into(),
|
||||||
)
|
);
|
||||||
} else {
|
} else {
|
||||||
//TODO: this element is added to workaround state issues
|
//TODO: this element is added to workaround state issues
|
||||||
widgets.push(horizontal_space().width(Length::Shrink).into());
|
widgets.push(horizontal_space().width(Length::Shrink).into());
|
||||||
|
|
@ -687,25 +686,19 @@ impl<App: Application> ApplicationExt for App {
|
||||||
let content_col = crate::widget::column::with_capacity(2)
|
let content_col = crate::widget::column::with_capacity(2)
|
||||||
.push(content_row)
|
.push(content_row)
|
||||||
.push_maybe(self.footer().map(|footer| {
|
.push_maybe(self.footer().map(|footer| {
|
||||||
container(footer.map(crate::Action::App)).padding([
|
container(footer.map(crate::Action::App)).padding([0, 0, 0, 0])
|
||||||
0,
|
|
||||||
border_padding,
|
|
||||||
border_padding,
|
|
||||||
border_padding,
|
|
||||||
])
|
|
||||||
}));
|
}));
|
||||||
let content_inset = if maximized { 0 } else { 16 };
|
|
||||||
let content: Element<_> = if content_container {
|
let content: Element<_> = if content_container {
|
||||||
let inner: Element<_> = content_col
|
let inner: Element<_> = content_col
|
||||||
.apply(container)
|
.apply(container)
|
||||||
.padding([7, 0, 0, 0])
|
.padding([0, 0, 0, 0])
|
||||||
.width(iced::Length::Fill)
|
.width(iced::Length::Fill)
|
||||||
.height(iced::Length::Fill)
|
.height(iced::Length::Fill)
|
||||||
.class(crate::theme::Container::ContentArea)
|
.class(crate::theme::Container::ContentArea)
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
container(inner)
|
container(inner)
|
||||||
.padding([8, content_inset, content_inset, content_inset])
|
.padding([0, 0, 0, 0])
|
||||||
.width(iced::Length::Fill)
|
.width(iced::Length::Fill)
|
||||||
.height(iced::Length::Fill)
|
.height(iced::Length::Fill)
|
||||||
.apply(|w| id_container(w, iced_core::id::Id::new("COSMIC_content_container")))
|
.apply(|w| id_container(w, iced_core::id::Id::new("COSMIC_content_container")))
|
||||||
|
|
@ -782,20 +775,13 @@ impl<App: Application> ApplicationExt for App {
|
||||||
// Needed to avoid header bar corner gaps for apps without a content container
|
// Needed to avoid header bar corner gaps for apps without a content container
|
||||||
header
|
header
|
||||||
.apply(container)
|
.apply(container)
|
||||||
.class(crate::theme::Container::custom(move |theme| {
|
.class(crate::theme::Container::custom(move |_theme| {
|
||||||
let cosmic = theme.cosmic();
|
|
||||||
container::Style {
|
container::Style {
|
||||||
background: Some(iced::Background::Color(
|
background: Some(iced::Background::Color(
|
||||||
cosmic.background.base.into(),
|
iced_core::Color::WHITE,
|
||||||
)),
|
)),
|
||||||
border: iced::Border {
|
border: iced::Border {
|
||||||
radius: [
|
radius: [0.0; 4].into(),
|
||||||
(window_corner_radius[0] - 1.0).max(0.0),
|
|
||||||
(window_corner_radius[1] - 1.0).max(0.0),
|
|
||||||
cosmic.radius_0()[2],
|
|
||||||
cosmic.radius_0()[3],
|
|
||||||
]
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
@ -810,19 +796,13 @@ impl<App: Application> ApplicationExt for App {
|
||||||
// The content element contains every element beneath the header.
|
// The content element contains every element beneath the header.
|
||||||
.push(content)
|
.push(content)
|
||||||
.apply(container)
|
.apply(container)
|
||||||
.padding(if maximized { 0 } else { 1 })
|
.padding(0)
|
||||||
.class(crate::theme::Container::custom(move |theme| {
|
.class(crate::theme::Container::custom(move |_theme| {
|
||||||
container::Style {
|
container::Style {
|
||||||
background: if content_container {
|
background: Some(iced::Background::Color(iced_core::Color::WHITE)),
|
||||||
Some(iced::Background::Color(
|
|
||||||
theme.cosmic().background.base.into(),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
border: iced::Border {
|
border: iced::Border {
|
||||||
color: theme.cosmic().bg_divider().into(),
|
color: iced_core::Color::TRANSPARENT,
|
||||||
width: if maximized { 0.0 } else { 1.0 },
|
width: 0.0,
|
||||||
radius: window_corner_radius.into(),
|
radius: window_corner_radius.into(),
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,26 @@ pub mod portal;
|
||||||
pub mod style;
|
pub mod style;
|
||||||
|
|
||||||
use cosmic_config::CosmicConfigEntry;
|
use cosmic_config::CosmicConfigEntry;
|
||||||
use cosmic_config::config_subscription;
|
|
||||||
use cosmic_theme::Component;
|
use cosmic_theme::Component;
|
||||||
use cosmic_theme::LayeredTheme;
|
use cosmic_theme::LayeredTheme;
|
||||||
use cosmic_theme::Spacing;
|
use cosmic_theme::Spacing;
|
||||||
use cosmic_theme::ThemeMode;
|
use cosmic_theme::ThemeMode;
|
||||||
use iced_futures::Subscription;
|
|
||||||
use iced_runtime::{Appearance, DefaultStyle};
|
use iced_runtime::{Appearance, DefaultStyle};
|
||||||
|
use palette::Srgba;
|
||||||
use std::sync::{Arc, LazyLock, Mutex};
|
use std::sync::{Arc, LazyLock, Mutex};
|
||||||
pub use style::*;
|
pub use style::*;
|
||||||
|
|
||||||
|
/// `state_default` color: rgb(0, 150, 136)
|
||||||
|
pub const STATE_DEFAULT_ACCENT: Srgba = Srgba::new(0.0, 0.588_235_3, 0.533_333_36, 1.0);
|
||||||
|
|
||||||
|
/// `state_default` as an iced Color
|
||||||
|
pub const STATE_DEFAULT_COLOR: iced_core::Color =
|
||||||
|
iced_core::Color::from_rgb(0.0, 0.588_235_3, 0.533_333_3);
|
||||||
|
|
||||||
|
/// `state_default` as an iced Color at 10% opacity
|
||||||
|
pub const STATE_DEFAULT_BG: iced_core::Color =
|
||||||
|
iced_core::Color::from_rgba(0.0, 0.588_235_3, 0.533_333_3, 0.10);
|
||||||
|
|
||||||
pub type CosmicColor = ::palette::rgb::Srgba;
|
pub type CosmicColor = ::palette::rgb::Srgba;
|
||||||
pub type CosmicComponent = cosmic_theme::Component;
|
pub type CosmicComponent = cosmic_theme::Component;
|
||||||
pub type CosmicTheme = cosmic_theme::Theme;
|
pub type CosmicTheme = cosmic_theme::Theme;
|
||||||
|
|
@ -126,6 +136,7 @@ pub fn system_dark() -> Theme {
|
||||||
theme
|
theme
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let t = t.with_accent(STATE_DEFAULT_ACCENT);
|
||||||
Theme::system(Arc::new(t))
|
Theme::system(Arc::new(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,6 +152,7 @@ pub fn system_light() -> Theme {
|
||||||
theme
|
theme
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let t = t.with_accent(STATE_DEFAULT_ACCENT);
|
||||||
Theme::system(Arc::new(t))
|
Theme::system(Arc::new(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,9 +154,9 @@ pub fn appearance(
|
||||||
|
|
||||||
if selected {
|
if selected {
|
||||||
appearance.background =
|
appearance.background =
|
||||||
Some(Background::Color(cosmic.primary.component.hover.into()));
|
Some(Background::Color(crate::theme::STATE_DEFAULT_BG));
|
||||||
appearance.icon_color = Some(cosmic.accent.base.into());
|
appearance.icon_color = Some(crate::theme::STATE_DEFAULT_COLOR);
|
||||||
appearance.text_color = Some(cosmic.accent_text_color().into());
|
appearance.text_color = Some(crate::theme::STATE_DEFAULT_COLOR);
|
||||||
} else {
|
} else {
|
||||||
appearance.background = Some(Background::Color(background));
|
appearance.background = Some(Background::Color(background));
|
||||||
appearance.icon_color = icon;
|
appearance.icon_color = icon;
|
||||||
|
|
@ -254,7 +254,15 @@ impl Catalog for crate::Theme {
|
||||||
Some(component.on.into())
|
Some(component.on.into())
|
||||||
};
|
};
|
||||||
|
|
||||||
(component.hover.into(), text_color, text_color)
|
if matches!(style, Button::ListItem) {
|
||||||
|
(
|
||||||
|
crate::theme::STATE_DEFAULT_BG,
|
||||||
|
text_color,
|
||||||
|
text_color,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(component.hover.into(), text_color, text_color)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -275,7 +283,15 @@ impl Catalog for crate::Theme {
|
||||||
Some(component.on.into())
|
Some(component.on.into())
|
||||||
};
|
};
|
||||||
|
|
||||||
(component.pressed.into(), text_color, text_color)
|
if matches!(style, Button::ListItem) {
|
||||||
|
(
|
||||||
|
crate::theme::STATE_DEFAULT_BG,
|
||||||
|
text_color,
|
||||||
|
text_color,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(component.pressed.into(), text_color, text_color)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use crate::Theme;
|
use crate::Theme;
|
||||||
|
use crate::theme::{STATE_DEFAULT_BG, STATE_DEFAULT_COLOR};
|
||||||
use crate::widget::dropdown;
|
use crate::widget::dropdown;
|
||||||
use iced::{Background, Color};
|
use iced::Background;
|
||||||
|
|
||||||
impl dropdown::menu::StyleSheet for Theme {
|
impl dropdown::menu::StyleSheet for Theme {
|
||||||
type Style = ();
|
type Style = ();
|
||||||
|
|
@ -16,13 +17,13 @@ impl dropdown::menu::StyleSheet for Theme {
|
||||||
background: Background::Color(cosmic.background.component.base.into()),
|
background: Background::Color(cosmic.background.component.base.into()),
|
||||||
border_width: 0.0,
|
border_width: 0.0,
|
||||||
border_radius: cosmic.corner_radii.radius_m.into(),
|
border_radius: cosmic.corner_radii.radius_m.into(),
|
||||||
border_color: Color::TRANSPARENT,
|
border_color: iced::Color::TRANSPARENT,
|
||||||
|
|
||||||
hovered_text_color: cosmic.on_bg_color().into(),
|
hovered_text_color: cosmic.on_bg_color().into(),
|
||||||
hovered_background: Background::Color(cosmic.primary.component.hover.into()),
|
hovered_background: Background::Color(STATE_DEFAULT_BG),
|
||||||
|
|
||||||
selected_text_color: cosmic.accent_text_color().into(),
|
selected_text_color: STATE_DEFAULT_COLOR,
|
||||||
selected_background: Background::Color(cosmic.primary.component.hover.into()),
|
selected_background: Background::Color(STATE_DEFAULT_BG),
|
||||||
|
|
||||||
description_color: cosmic.primary.component.on_disabled.into(),
|
description_color: cosmic.primary.component.on_disabled.into(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -599,11 +599,11 @@ impl iced_container::Catalog for Theme {
|
||||||
Container::ContentArea => iced_container::Style {
|
Container::ContentArea => iced_container::Style {
|
||||||
icon_color: Some(Color::from(cosmic.background.on)),
|
icon_color: Some(Color::from(cosmic.background.on)),
|
||||||
text_color: Some(Color::from(cosmic.background.on)),
|
text_color: Some(Color::from(cosmic.background.on)),
|
||||||
background: Some(iced::Background::Color(cosmic.background.base.into())),
|
background: Some(iced::Background::Color(Color::from_rgb8(245, 245, 245))),
|
||||||
border: Border {
|
border: Border {
|
||||||
radius: cosmic.corner_radii.radius_s.into(),
|
radius: [0.0; 4].into(),
|
||||||
width: 1.0,
|
width: 0.0,
|
||||||
color: cosmic.background.divider.into(),
|
color: Color::TRANSPARENT,
|
||||||
},
|
},
|
||||||
shadow: Shadow::default(),
|
shadow: Shadow::default(),
|
||||||
},
|
},
|
||||||
|
|
@ -693,56 +693,42 @@ impl slider::Catalog for Theme {
|
||||||
|
|
||||||
fn style(&self, class: &Self::Class<'_>, status: slider::Status) -> slider::Style {
|
fn style(&self, class: &Self::Class<'_>, status: slider::Status) -> slider::Style {
|
||||||
let cosmic: &cosmic_theme::Theme = self.cosmic();
|
let cosmic: &cosmic_theme::Theme = self.cosmic();
|
||||||
let hc = self.theme_type.is_high_contrast();
|
|
||||||
let is_dark = self.theme_type.is_dark();
|
|
||||||
|
|
||||||
let mut appearance = match class {
|
let mut appearance = match class {
|
||||||
Slider::Standard =>
|
Slider::Standard =>
|
||||||
//TODO: no way to set rail thickness
|
//TODO: no way to set rail thickness
|
||||||
{
|
{
|
||||||
let (active_track, inactive_track) = if hc {
|
let empty_track: Color = Color::from_rgb8(224, 224, 224);
|
||||||
(
|
|
||||||
cosmic.accent_text_color(),
|
|
||||||
if is_dark {
|
|
||||||
cosmic.palette.neutral_5
|
|
||||||
} else {
|
|
||||||
cosmic.palette.neutral_3
|
|
||||||
},
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(cosmic.accent.base, cosmic.palette.neutral_6)
|
|
||||||
};
|
|
||||||
slider::Style {
|
slider::Style {
|
||||||
rail: Rail {
|
rail: Rail {
|
||||||
backgrounds: (
|
backgrounds: (
|
||||||
Background::Color(active_track.into()),
|
Background::Color(crate::theme::STATE_DEFAULT_COLOR),
|
||||||
Background::Color(inactive_track.into()),
|
Background::Color(empty_track),
|
||||||
),
|
),
|
||||||
border: Border {
|
border: Border {
|
||||||
radius: cosmic.corner_radii.radius_xs.into(),
|
radius: cosmic.corner_radii.radius_xs.into(),
|
||||||
color: if hc && !is_dark {
|
color: Color::TRANSPARENT,
|
||||||
self.current_container().component.border.into()
|
width: 0.0,
|
||||||
} else {
|
|
||||||
Color::TRANSPARENT
|
|
||||||
},
|
|
||||||
width: if hc && !is_dark { 1. } else { 0. },
|
|
||||||
},
|
},
|
||||||
width: 4.0,
|
width: 4.0,
|
||||||
},
|
},
|
||||||
|
|
||||||
handle: slider::Handle {
|
handle: slider::Handle {
|
||||||
shape: slider::HandleShape::Rectangle {
|
shape: slider::HandleShape::Circle {
|
||||||
height: 20,
|
radius: 8.0,
|
||||||
width: 20,
|
},
|
||||||
border_radius: cosmic.corner_radii.radius_m.into(),
|
border_color: Color::from_rgba8(0, 0, 0, 0.12),
|
||||||
|
border_width: 1.0,
|
||||||
|
background: Background::Color(Color::WHITE),
|
||||||
|
shadow: Shadow {
|
||||||
|
color: Color::from_rgba8(0, 0, 0, 0.10),
|
||||||
|
offset: Vector::new(0.0, 1.0),
|
||||||
|
blur_radius: 3.0,
|
||||||
},
|
},
|
||||||
border_color: Color::TRANSPARENT,
|
|
||||||
border_width: 0.0,
|
|
||||||
background: Background::Color(cosmic.accent.base.into()),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
breakpoint: slider::Breakpoint {
|
breakpoint: slider::Breakpoint {
|
||||||
color: cosmic.on_bg_color().into(),
|
color: crate::theme::STATE_DEFAULT_COLOR,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -752,34 +738,33 @@ impl slider::Catalog for Theme {
|
||||||
slider::Status::Active => appearance,
|
slider::Status::Active => appearance,
|
||||||
slider::Status::Hovered => match class {
|
slider::Status::Hovered => match class {
|
||||||
Slider::Standard => {
|
Slider::Standard => {
|
||||||
appearance.handle.shape = slider::HandleShape::Rectangle {
|
appearance.handle.shape = slider::HandleShape::Circle {
|
||||||
height: 26,
|
radius: 10.0,
|
||||||
width: 26,
|
};
|
||||||
border_radius: cosmic.corner_radii.radius_m.into(),
|
appearance.handle.border_width = 1.0;
|
||||||
|
appearance.handle.border_color = Color::from_rgba8(0, 0, 0, 0.12);
|
||||||
|
appearance.handle.shadow = Shadow {
|
||||||
|
color: Color::from_rgba8(0, 0, 0, 0.12),
|
||||||
|
offset: Vector::new(0.0, 1.0),
|
||||||
|
blur_radius: 4.0,
|
||||||
};
|
};
|
||||||
appearance.handle.border_width = 3.0;
|
|
||||||
appearance.handle.border_color =
|
|
||||||
self.cosmic().palette.neutral_10.with_alpha(0.1).into();
|
|
||||||
appearance
|
appearance
|
||||||
}
|
}
|
||||||
Slider::Custom { hovered, .. } => hovered(self),
|
Slider::Custom { hovered, .. } => hovered(self),
|
||||||
},
|
},
|
||||||
slider::Status::Dragged => match class {
|
slider::Status::Dragged => match class {
|
||||||
Slider::Standard => {
|
Slider::Standard => {
|
||||||
let mut style = {
|
appearance.handle.shape = slider::HandleShape::Circle {
|
||||||
appearance.handle.shape = slider::HandleShape::Rectangle {
|
radius: 10.0,
|
||||||
height: 26,
|
|
||||||
width: 26,
|
|
||||||
border_radius: cosmic.corner_radii.radius_m.into(),
|
|
||||||
};
|
|
||||||
appearance.handle.border_width = 3.0;
|
|
||||||
appearance.handle.border_color =
|
|
||||||
self.cosmic().palette.neutral_10.with_alpha(0.1).into();
|
|
||||||
appearance
|
|
||||||
};
|
};
|
||||||
style.handle.border_color =
|
appearance.handle.border_width = 1.0;
|
||||||
self.cosmic().palette.neutral_10.with_alpha(0.2).into();
|
appearance.handle.border_color = Color::from_rgba8(0, 0, 0, 0.12);
|
||||||
style
|
appearance.handle.shadow = Shadow {
|
||||||
|
color: Color::from_rgba8(0, 0, 0, 0.12),
|
||||||
|
offset: Vector::new(0.0, 1.0),
|
||||||
|
blur_radius: 4.0,
|
||||||
|
};
|
||||||
|
appearance
|
||||||
}
|
}
|
||||||
Slider::Custom { dragging, .. } => dragging(self),
|
Slider::Custom { dragging, .. } => dragging(self),
|
||||||
},
|
},
|
||||||
|
|
@ -802,8 +787,8 @@ impl menu::Catalog for Theme {
|
||||||
radius: cosmic.corner_radii.radius_m.into(),
|
radius: cosmic.corner_radii.radius_m.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
selected_text_color: cosmic.accent_text_color().into(),
|
selected_text_color: crate::theme::STATE_DEFAULT_COLOR,
|
||||||
selected_background: Background::Color(cosmic.background.component.hover.into()),
|
selected_background: Background::Color(crate::theme::STATE_DEFAULT_BG),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,10 +71,41 @@ impl StyleSheet for Theme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SegmentedButton::NavBar | SegmentedButton::FileNav => Appearance {
|
SegmentedButton::NavBar | SegmentedButton::FileNav => {
|
||||||
active_width: 0.0,
|
let rad_m = cosmic.corner_radii.radius_m;
|
||||||
..horizontal::tab_bar(cosmic, container)
|
let item_border = ItemAppearance {
|
||||||
},
|
border: Border {
|
||||||
|
radius: rad_m.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let active = ItemStatusAppearance {
|
||||||
|
background: Some(Background::Color(crate::theme::STATE_DEFAULT_BG)),
|
||||||
|
first: item_border,
|
||||||
|
middle: item_border,
|
||||||
|
last: item_border,
|
||||||
|
text_color: crate::theme::STATE_DEFAULT_COLOR,
|
||||||
|
};
|
||||||
|
let inactive = ItemStatusAppearance {
|
||||||
|
background: None,
|
||||||
|
first: item_border,
|
||||||
|
middle: item_border,
|
||||||
|
last: item_border,
|
||||||
|
text_color: container.component.on.into(),
|
||||||
|
};
|
||||||
|
Appearance {
|
||||||
|
active_width: 0.0,
|
||||||
|
border: Border {
|
||||||
|
radius: cosmic.corner_radii.radius_0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
inactive,
|
||||||
|
hover: inactive,
|
||||||
|
pressed: inactive,
|
||||||
|
active,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SegmentedButton::TabBar => horizontal::tab_bar(cosmic, container),
|
SegmentedButton::TabBar => horizontal::tab_bar(cosmic, container),
|
||||||
|
|
||||||
|
|
@ -126,10 +157,51 @@ impl StyleSheet for Theme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SegmentedButton::NavBar | SegmentedButton::FileNav => Appearance {
|
SegmentedButton::NavBar | SegmentedButton::FileNav => {
|
||||||
active_width: 0.0,
|
let rad_m = cosmic.corner_radii.radius_m;
|
||||||
..vertical::tab_bar(cosmic, container)
|
let active = ItemStatusAppearance {
|
||||||
},
|
background: Some(Background::Color(crate::theme::STATE_DEFAULT_BG)),
|
||||||
|
first: ItemAppearance {
|
||||||
|
border: Border {
|
||||||
|
radius: rad_m.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
middle: ItemAppearance {
|
||||||
|
border: Border {
|
||||||
|
radius: rad_m.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
last: ItemAppearance {
|
||||||
|
border: Border {
|
||||||
|
radius: rad_m.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
text_color: crate::theme::STATE_DEFAULT_COLOR,
|
||||||
|
};
|
||||||
|
let inactive = ItemStatusAppearance {
|
||||||
|
background: None,
|
||||||
|
first: active.first,
|
||||||
|
middle: active.middle,
|
||||||
|
last: active.last,
|
||||||
|
text_color: container.component.on.into(),
|
||||||
|
};
|
||||||
|
let hover_state = inactive;
|
||||||
|
Appearance {
|
||||||
|
active_width: 0.0,
|
||||||
|
border: Border {
|
||||||
|
radius: cosmic.corner_radii.radius_0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
inactive,
|
||||||
|
hover: hover_state,
|
||||||
|
pressed: hover_state,
|
||||||
|
active,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SegmentedButton::TabBar => vertical::tab_bar(cosmic, container),
|
SegmentedButton::TabBar => vertical::tab_bar(cosmic, container),
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -441,15 +441,7 @@ impl<'a, Message: Clone + 'static> HeaderBar<'a, Message> {
|
||||||
(portion, portion)
|
(portion, portion)
|
||||||
};
|
};
|
||||||
|
|
||||||
// SSD uses fixed height 48px with 12px horizontal padding; non-SSD uses computed height
|
let (header_height, header_padding) = (Length::Fixed(48.0), [8, 12, 8, 12]);
|
||||||
let (header_height, header_padding) = if self.is_ssd {
|
|
||||||
(Length::Fixed(48.0), [8, 12, 8, 12])
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
Length::Fixed(44.0 + padding[0] as f32 + padding[2] as f32),
|
|
||||||
if self.is_ssd { [0, 8, 0, 8] } else { padding },
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Creates the headerbar widget.
|
// Creates the headerbar widget.
|
||||||
let widget = widget::row::with_capacity(3)
|
let widget = widget::row::with_capacity(3)
|
||||||
|
|
@ -498,50 +490,31 @@ impl<'a, Message: Clone + 'static> HeaderBar<'a, Message> {
|
||||||
.padding(header_padding)
|
.padding(header_padding)
|
||||||
.spacing(8)
|
.spacing(8)
|
||||||
.apply(widget::container)
|
.apply(widget::container)
|
||||||
.class(if self.is_ssd {
|
.class({
|
||||||
// SSD: custom container with white background and top corner radii
|
|
||||||
let sharp = self.sharp_corners;
|
|
||||||
let explicit_radius = self.corner_radius;
|
|
||||||
crate::theme::Container::custom(move |theme| {
|
crate::theme::Container::custom(move |theme| {
|
||||||
let cosmic = theme.cosmic();
|
let cosmic = theme.cosmic();
|
||||||
let window_radius = explicit_radius.unwrap_or_else(|| cosmic.radius_window());
|
|
||||||
iced_widget::container::Style {
|
iced_widget::container::Style {
|
||||||
icon_color: Some(Color::from(cosmic.background.on)),
|
icon_color: Some(Color::from(cosmic.background.on)),
|
||||||
text_color: Some(Color::from(cosmic.background.on)),
|
text_color: Some(Color::from(cosmic.background.on)),
|
||||||
background: Some(iced::Background::Color(Color::from_rgba8(
|
background: Some(iced::Background::Color(Color::WHITE)),
|
||||||
255, 255, 255, 0.99,
|
|
||||||
))),
|
|
||||||
border: Border {
|
border: Border {
|
||||||
radius: [
|
radius: [0.0; 4].into(),
|
||||||
if sharp { 0.0 } else { window_radius[0] },
|
|
||||||
if sharp { 0.0 } else { window_radius[1] },
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
]
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
shadow: Default::default(),
|
shadow: Default::default(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
crate::theme::Container::HeaderBar {
|
|
||||||
focused: self.focused,
|
|
||||||
sharp_corners: self.sharp_corners,
|
|
||||||
transparent: self.transparent,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.center_y(Length::Shrink);
|
.center_y(Length::Shrink);
|
||||||
|
|
||||||
// SSD: add 1px horizontal rule below header with color #F0F0F1
|
let widget = {
|
||||||
let widget = if self.is_ssd {
|
|
||||||
use iced::widget::{horizontal_rule, rule};
|
use iced::widget::{horizontal_rule, rule};
|
||||||
widget::column::with_capacity(2)
|
widget::column::with_capacity(2)
|
||||||
.push(widget)
|
.push(widget)
|
||||||
.push(
|
.push(
|
||||||
horizontal_rule(1).class(crate::theme::Rule::Custom(Box::new(
|
horizontal_rule(1).class(crate::theme::Rule::Custom(Box::new(
|
||||||
|_: &crate::Theme| rule::Style {
|
|_: &crate::Theme| rule::Style {
|
||||||
color: Color::from_rgba8(240, 240, 241, 1.0),
|
color: Color::from_rgba8(224, 224, 224, 1.0),
|
||||||
width: 1,
|
width: 1,
|
||||||
radius: 0.0.into(),
|
radius: 0.0.into(),
|
||||||
fill_mode: rule::FillMode::Full,
|
fill_mode: rule::FillMode::Full,
|
||||||
|
|
@ -549,8 +522,6 @@ impl<'a, Message: Clone + 'static> HeaderBar<'a, Message> {
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
.apply(widget::mouse_area)
|
.apply(widget::mouse_area)
|
||||||
} else {
|
|
||||||
widget.apply(widget::mouse_area)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut widget = widget;
|
let mut widget = widget;
|
||||||
|
|
@ -586,89 +557,98 @@ impl<'a, Message: Clone + 'static> HeaderBar<'a, Message> {
|
||||||
const ICON_RESTORE: &[u8] = include_bytes!("../../res/icons/window-restore.svg");
|
const ICON_RESTORE: &[u8] = include_bytes!("../../res/icons/window-restore.svg");
|
||||||
const ICON_CLOSE: &[u8] = include_bytes!("../../res/icons/window-close.svg");
|
const ICON_CLOSE: &[u8] = include_bytes!("../../res/icons/window-close.svg");
|
||||||
|
|
||||||
// SSD uses custom styling: fill_strong bg, space_xs padding, 2px gap
|
macro_rules! wc_icon {
|
||||||
let is_ssd = self.is_ssd;
|
($svg_bytes:expr, $size:expr, $on_press:expr, $is_close:expr) => {{
|
||||||
|
let icon_w = widget::icon::icon(widget::icon::from_svg_bytes($svg_bytes))
|
||||||
macro_rules! icon {
|
.size($size)
|
||||||
($svg_bytes:expr, $size:expr, $on_press:expr) => {{
|
.class(crate::theme::Svg::custom(|_| iced::widget::svg::Style {
|
||||||
let padding = if is_ssd { [6, 6] } else { [8, 8] };
|
color: Some(Color::from_rgb8(0x3D, 0x3D, 0x3D)),
|
||||||
let result: Element<'a, Message> = if is_ssd {
|
}));
|
||||||
// SSD: create icon widget with dark tint, wrap in custom button
|
let btn: Element<'a, Message> = widget::button::custom(icon_w)
|
||||||
let icon_w = widget::icon::icon(widget::icon::from_svg_bytes($svg_bytes))
|
.padding([4, 6])
|
||||||
.size($size)
|
.class(crate::theme::Button::Custom {
|
||||||
.class(crate::theme::Svg::custom(|_| iced::widget::svg::Style {
|
active: Box::new(move |_focused, _theme| {
|
||||||
color: Some(Color::from_rgb8(0x1B, 0x1B, 0x1B)),
|
crate::widget::button::Style {
|
||||||
}));
|
background: Some(iced::Background::Color(Color::TRANSPARENT)),
|
||||||
widget::button::custom(icon_w)
|
text_color: Some(Color::from_rgb8(0x3D, 0x3D, 0x3D)),
|
||||||
.padding(padding)
|
icon_color: Some(Color::from_rgb8(0x3D, 0x3D, 0x3D)),
|
||||||
.class(crate::theme::Button::HeaderBar)
|
border_radius: [6.0; 4].into(),
|
||||||
.selected(self.focused)
|
..Default::default()
|
||||||
.on_press($on_press)
|
}
|
||||||
.into()
|
}),
|
||||||
} else {
|
disabled: Box::new(|_theme| crate::widget::button::Style::default()),
|
||||||
widget::icon::from_svg_bytes($svg_bytes)
|
hovered: Box::new(move |_focused, _theme| {
|
||||||
.apply(widget::button::icon)
|
let bg = if $is_close {
|
||||||
.padding(padding)
|
Color::from_rgba8(224, 64, 64, 0.20)
|
||||||
.class(crate::theme::Button::HeaderBar)
|
} else {
|
||||||
.selected(self.focused)
|
Color::from_rgb8(208, 208, 208)
|
||||||
.icon_size($size)
|
};
|
||||||
.on_press($on_press)
|
let icon_c = if $is_close {
|
||||||
.into()
|
Color::from_rgb8(224, 64, 64)
|
||||||
};
|
} else {
|
||||||
result
|
Color::from_rgb8(0x3D, 0x3D, 0x3D)
|
||||||
|
};
|
||||||
|
crate::widget::button::Style {
|
||||||
|
background: Some(iced::Background::Color(bg)),
|
||||||
|
text_color: Some(icon_c),
|
||||||
|
icon_color: Some(icon_c),
|
||||||
|
border_radius: [6.0; 4].into(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
pressed: Box::new(move |_focused, _theme| {
|
||||||
|
let bg = if $is_close {
|
||||||
|
Color::from_rgba8(200, 50, 50, 0.30)
|
||||||
|
} else {
|
||||||
|
Color::from_rgb8(190, 190, 190)
|
||||||
|
};
|
||||||
|
let icon_c = if $is_close {
|
||||||
|
Color::from_rgb8(200, 50, 50)
|
||||||
|
} else {
|
||||||
|
Color::from_rgb8(0x3D, 0x3D, 0x3D)
|
||||||
|
};
|
||||||
|
crate::widget::button::Style {
|
||||||
|
background: Some(iced::Background::Color(bg)),
|
||||||
|
text_color: Some(icon_c),
|
||||||
|
icon_color: Some(icon_c),
|
||||||
|
border_radius: [6.0; 4].into(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.on_press($on_press)
|
||||||
|
.into();
|
||||||
|
btn
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSD: 2px gap between icons; non-SSD: space_xxs
|
|
||||||
let icon_spacing = if self.is_ssd {
|
|
||||||
2
|
|
||||||
} else {
|
|
||||||
theme::spacing().space_xxs
|
|
||||||
};
|
|
||||||
|
|
||||||
widget::row::with_capacity(3)
|
widget::row::with_capacity(3)
|
||||||
.push_maybe(
|
.push_maybe(
|
||||||
self.on_minimize
|
self.on_minimize
|
||||||
.take()
|
.take()
|
||||||
.map(|m: Message| icon!(ICON_MINIMIZE, 16, m)),
|
.map(|m: Message| wc_icon!(ICON_MINIMIZE, 14, m, false)),
|
||||||
)
|
)
|
||||||
.push_maybe(self.on_maximize.take().map(|m| {
|
.push_maybe(self.on_maximize.take().map(|m| {
|
||||||
if self.maximized {
|
if self.maximized {
|
||||||
icon!(ICON_RESTORE, 16, m)
|
wc_icon!(ICON_RESTORE, 14, m, false)
|
||||||
} else {
|
} else {
|
||||||
icon!(ICON_MAXIMIZE, 16, m)
|
wc_icon!(ICON_MAXIMIZE, 14, m, false)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.push_maybe(self.on_close.take().map(|m| icon!(ICON_CLOSE, 16, m)))
|
.push_maybe(self.on_close.take().map(|m| wc_icon!(ICON_CLOSE, 14, m, true)))
|
||||||
.spacing(icon_spacing)
|
.spacing(2)
|
||||||
.apply(widget::container)
|
.apply(widget::container)
|
||||||
.class(crate::theme::Container::custom(move |theme| {
|
.class(crate::theme::Container::custom(move |_theme| {
|
||||||
let cosmic = theme.cosmic();
|
|
||||||
// SSD uses white at 80% opacity; non-SSD uses component base
|
|
||||||
let background = if is_ssd {
|
|
||||||
Color::from_rgba8(0xFF, 0xFF, 0xFF, 0.80)
|
|
||||||
} else {
|
|
||||||
Color::from(cosmic.background.component.base)
|
|
||||||
};
|
|
||||||
iced_widget::container::Style {
|
iced_widget::container::Style {
|
||||||
background: Some(iced::Background::Color(background)),
|
background: Some(iced::Background::Color(Color::from_rgb8(232, 232, 232))),
|
||||||
border: Border {
|
border: Border {
|
||||||
radius: cosmic.corner_radii.radius_xl.into(),
|
radius: [8.0; 4].into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
// SSD: 8px horizontal, 2px vertical; non-SSD: [4, 8]
|
.padding([2, 4])
|
||||||
.padding(if self.is_ssd { [2, 8] } else { [4, 8] })
|
|
||||||
.center_y(Length::Fill)
|
|
||||||
// SSD: 18px left margin so title never gets too close
|
|
||||||
.apply(widget::container)
|
|
||||||
.padding(if self.is_ssd {
|
|
||||||
iced::Padding::from([0, 0, 0, 18])
|
|
||||||
} else {
|
|
||||||
iced::Padding::ZERO
|
|
||||||
})
|
|
||||||
.center_y(Length::Fill)
|
.center_y(Length::Fill)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -173,11 +173,11 @@ pub fn nav_bar_style(theme: &Theme) -> iced_widget::container::Style {
|
||||||
iced_widget::container::Style {
|
iced_widget::container::Style {
|
||||||
icon_color: Some(cosmic.on_bg_color().into()),
|
icon_color: Some(cosmic.on_bg_color().into()),
|
||||||
text_color: Some(cosmic.on_bg_color().into()),
|
text_color: Some(cosmic.on_bg_color().into()),
|
||||||
background: Some(Background::Color(cosmic.primary.base.into())),
|
background: Some(Background::Color(Color::WHITE)),
|
||||||
border: Border {
|
border: Border {
|
||||||
width: 0.0,
|
width: 0.0,
|
||||||
color: Color::TRANSPARENT,
|
color: Color::TRANSPARENT,
|
||||||
radius: cosmic.corner_radii.radius_s.into(),
|
radius: [0.0; 4].into(),
|
||||||
},
|
},
|
||||||
shadow: Shadow::default(),
|
shadow: Shadow::default(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -216,8 +216,8 @@ where
|
||||||
minimum_button_width: u16::MIN,
|
minimum_button_width: u16::MIN,
|
||||||
maximum_button_width: u16::MAX,
|
maximum_button_width: u16::MAX,
|
||||||
indent_spacing: 16,
|
indent_spacing: 16,
|
||||||
font_active: crate::font::semibold(),
|
font_active: crate::font::default(),
|
||||||
font_hovered: crate::font::semibold(),
|
font_hovered: crate::font::default(),
|
||||||
font_inactive: crate::font::default(),
|
font_inactive: crate::font::default(),
|
||||||
font_size: 14.0,
|
font_size: 14.0,
|
||||||
height: Length::Shrink,
|
height: Length::Shrink,
|
||||||
|
|
@ -1796,10 +1796,10 @@ where
|
||||||
let key_is_hovered = self.button_is_hovered(state, key);
|
let key_is_hovered = self.button_is_hovered(state, key);
|
||||||
let status_appearance = if self.button_is_pressed(state, key) {
|
let status_appearance = if self.button_is_pressed(state, key) {
|
||||||
appearance.pressed
|
appearance.pressed
|
||||||
} else if key_is_hovered || menu_open() {
|
|
||||||
appearance.hover
|
|
||||||
} else if key_is_active {
|
} else if key_is_active {
|
||||||
appearance.active
|
appearance.active
|
||||||
|
} else if key_is_hovered || menu_open() {
|
||||||
|
appearance.hover
|
||||||
} else {
|
} else {
|
||||||
appearance.inactive
|
appearance.inactive
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue