Files
feresaria/shell/ferese-settings/src/form_controls.rs
T

232 lines
8.8 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()
}
}