257 lines
9.3 KiB
Rust
257 lines
9.3 KiB
Rust
use cosmic::widget::column;
|
|
|
|
use super::{
|
|
Alignment, App, Element, Field, Kind, Length, Message, button, container, row, set, slider,
|
|
text_input, visuals, widget,
|
|
};
|
|
|
|
impl App {
|
|
pub(super) fn label<'a>(
|
|
&self,
|
|
text: impl Into<std::borrow::Cow<'a, str>> + 'a,
|
|
size: f32,
|
|
) -> widget::Text<'a, cosmic::Theme, cosmic::Renderer> {
|
|
ferese_theme::text(text, self.font).size(size)
|
|
}
|
|
|
|
pub(super) fn panel_heading(
|
|
&self,
|
|
text: impl Into<std::borrow::Cow<'static, str>> + 'static,
|
|
size: f32,
|
|
) -> widget::Text<'static, cosmic::Theme, cosmic::Renderer> {
|
|
self.label(text, size).font(cosmic::iced::Font {
|
|
weight: cosmic::iced::font::Weight::Semibold,
|
|
..self.font
|
|
})
|
|
}
|
|
|
|
pub(super) fn note(&self, text: &str) -> Element<'static, Message> {
|
|
let palette = visuals::Palette::from_resolved(&self.resolved.presented);
|
|
self.label(
|
|
text.to_owned(),
|
|
if self.page == crate::schema::Page::Bar {
|
|
12.
|
|
} else {
|
|
11.
|
|
},
|
|
)
|
|
.class(cosmic::theme::Text::Color(palette.muted))
|
|
.into()
|
|
}
|
|
|
|
fn control_button_style(
|
|
&self,
|
|
palette: visuals::Palette,
|
|
selected: bool,
|
|
) -> cosmic::theme::Button {
|
|
if self.page == crate::schema::Page::Bar {
|
|
visuals::panel_button(palette, selected)
|
|
} else {
|
|
visuals::button_style(palette, selected)
|
|
}
|
|
}
|
|
|
|
pub(super) fn settings_button(
|
|
&self,
|
|
label: &str,
|
|
icon: &str,
|
|
message: Option<Message>,
|
|
selected: bool,
|
|
) -> Element<'static, Message> {
|
|
let palette = visuals::Palette::from_resolved(&self.resolved.presented);
|
|
button::custom(
|
|
row([])
|
|
.spacing(5)
|
|
.align_y(Alignment::Center)
|
|
.push(visuals::action_icon(
|
|
icon,
|
|
if message.is_some() {
|
|
palette.text
|
|
} else {
|
|
palette.muted
|
|
},
|
|
))
|
|
.push(self.label(label.to_owned(), 12.)),
|
|
)
|
|
.name(label.to_owned())
|
|
.padding([4, 8])
|
|
.class(self.control_button_style(palette, selected))
|
|
.on_press_maybe(message)
|
|
.into()
|
|
}
|
|
|
|
pub(super) fn settings_icon_button(
|
|
&self,
|
|
label: &str,
|
|
icon: &str,
|
|
message: Option<Message>,
|
|
) -> Element<'static, Message> {
|
|
let palette = visuals::Palette::from_resolved(&self.resolved.presented);
|
|
widget::tooltip(
|
|
button::custom(visuals::action_icon(
|
|
icon,
|
|
if message.is_some() {
|
|
palette.text
|
|
} else {
|
|
palette.muted
|
|
},
|
|
))
|
|
.name(label.to_owned())
|
|
.padding(4)
|
|
.class(self.control_button_style(palette, false))
|
|
.on_press_maybe(message),
|
|
self.label(label.to_owned(), 11.),
|
|
widget::tooltip::Position::Top,
|
|
)
|
|
.into()
|
|
}
|
|
|
|
pub(super) fn field(&self, mut field: Field) -> Element<'static, Message> {
|
|
if field.path == "theme.material.opacity" {
|
|
let appearance = self.resolved.theme.appearance;
|
|
let name = match appearance {
|
|
ferese_config::theme::Appearance::Light => "light",
|
|
ferese_config::theme::Appearance::Dark => "dark",
|
|
};
|
|
field.path = format!("theme.{name}.material.opacity");
|
|
field.description =
|
|
format!("Opacity for the current {name} appearance. Text and icons stay opaque.");
|
|
if let Kind::Range { default, .. } = &mut field.kind {
|
|
*default = self.resolved.theme.tokens.material.opacity;
|
|
}
|
|
}
|
|
let palette = visuals::Palette::from_resolved(&self.resolved.presented);
|
|
let mut labels = column([])
|
|
.spacing(2)
|
|
.push(self.label(field.label.clone(), 13.));
|
|
if !field.description.is_empty() {
|
|
labels = labels.push(
|
|
self.label(field.description.clone(), 11.)
|
|
.class(cosmic::theme::Text::Color(palette.muted)),
|
|
);
|
|
}
|
|
let labels = labels.width(Length::Fill);
|
|
let path = field.path.clone();
|
|
let control: Element<'static, Message> = match field.kind.clone() {
|
|
Kind::Toggle(default) => {
|
|
let enabled = self.draft.boolean(&path, default);
|
|
ferese_theme::controls::switch(enabled, palette)
|
|
.name(format!(
|
|
"{}: {}",
|
|
field.label,
|
|
if enabled { "on" } else { "off" }
|
|
))
|
|
.on_press(Message::Change(set(&path, !enabled)))
|
|
.into()
|
|
}
|
|
Kind::Range {
|
|
default,
|
|
min,
|
|
mut max,
|
|
step,
|
|
suffix,
|
|
integer,
|
|
} => {
|
|
let margin_limit = (path == "panels.0.geometry.side_margins")
|
|
.then(|| self.panel_side_margin_limit());
|
|
if let Some(limit) = margin_limit {
|
|
max = f64::from(limit.unwrap_or(0));
|
|
}
|
|
let value = self
|
|
.ranges
|
|
.get(&path)
|
|
.copied()
|
|
.unwrap_or_else(|| self.draft.number(&path, default))
|
|
.clamp(min, max);
|
|
let display = if integer || step >= 1. {
|
|
format!("{value:.0}{suffix}")
|
|
} else {
|
|
format!("{value:.2}{suffix}")
|
|
};
|
|
if margin_limit == Some(None) {
|
|
self.label("—", 12.).into()
|
|
} else if max <= min {
|
|
self.label(display, 12.).into()
|
|
} else {
|
|
let release = field.clone();
|
|
row([])
|
|
.align_y(Alignment::Center)
|
|
.spacing(8)
|
|
.push(
|
|
slider(min..=max, value, move |value| {
|
|
Message::Range(field.clone(), value)
|
|
})
|
|
.step(step)
|
|
.class(ferese_theme::menus::slider(palette.accent, 1.))
|
|
.on_release(Message::Release(release))
|
|
.width(145),
|
|
)
|
|
.push(self.label(display, 12.).width(65))
|
|
.into()
|
|
}
|
|
}
|
|
Kind::Choice { default, choices } => {
|
|
let value = self.wallpaper_field_value(&path, default);
|
|
let mut options = row([]).spacing(2);
|
|
for (key, label) in choices {
|
|
options = options.push(
|
|
button::custom(self.label(*label, 12.))
|
|
.padding([4, 8])
|
|
.class(self.control_button_style(palette, value == *key))
|
|
.on_press(Message::Change(set(&path, *key))),
|
|
);
|
|
}
|
|
container(options)
|
|
.padding(3)
|
|
.class(visuals::surface(palette.sidebar, 10.))
|
|
.into()
|
|
}
|
|
Kind::Text { default, argv } => {
|
|
let value = self.inputs.get(&path).cloned().unwrap_or_else(|| {
|
|
if argv {
|
|
self.draft.argv(&path)
|
|
} else {
|
|
self.wallpaper_field_value(&path, default)
|
|
}
|
|
});
|
|
let commit = field.clone();
|
|
let is_color = path.starts_with("theme.colors.");
|
|
let swatch = visuals::color(&value, palette.accent);
|
|
let input = text_input(default, value)
|
|
.font(self.font)
|
|
.padding([4, 8])
|
|
.style(visuals::input_style(palette))
|
|
.on_input(move |value| Message::Draft(path.clone(), value))
|
|
.on_submit(move |_| Message::Commit(field.clone()))
|
|
.on_unfocus(Message::Commit(commit))
|
|
.width(if is_color { 155 } else { 225 })
|
|
.size(12);
|
|
if is_color {
|
|
row([])
|
|
.spacing(8)
|
|
.align_y(Alignment::Center)
|
|
.push(
|
|
container(widget::Space::new().width(24).height(24))
|
|
.class(visuals::surface(swatch, 6.)),
|
|
)
|
|
.push(input)
|
|
.into()
|
|
} else {
|
|
input.into()
|
|
}
|
|
}
|
|
};
|
|
container(
|
|
row([])
|
|
.spacing(10)
|
|
.align_y(Alignment::Center)
|
|
.push(labels)
|
|
.push(control),
|
|
)
|
|
.padding([7, 10])
|
|
.width(Length::Fill)
|
|
.class(visuals::surface(palette.card, 0.))
|
|
.into()
|
|
}
|
|
}
|