Files
feresaria/shell/ferese-shell/src/status_ui/controls.rs
T

209 lines
5.9 KiB
Rust

use cosmic::iced::border::Shape as BorderShape;
use cosmic::iced::{Alignment, Background, Border, Color, Length};
use cosmic::widget::{button, column, container, row, slider};
use cosmic::{Element, theme};
use crate::status::Action;
use crate::{Message, ShellTheme, accented_icon, color, color_with_opacity, motion};
pub(super) fn status_summary<'a>(
render: crate::rendering::Rendering,
source: &'static [u8],
title: &'a str,
subtitle: &'a str,
style: super::MenuStyle,
enabled: bool,
toggle: Option<(bool, Action)>,
) -> Element<'a, cosmic::Action<Message>> {
let super::MenuStyle {
theme,
primary,
muted,
opacity,
} = style;
let accent = color_with_opacity(theme.accent, opacity);
let badge_color = if enabled { accent } else { primary };
let badge = container(accented_icon(source, 22, primary, accent))
.width(32)
.height(32)
.center_x(32)
.center_y(32)
.class(theme::Container::custom(move |_| container::Style {
background: Some(Background::Color(Color {
a: if enabled {
0.22 * opacity
} else {
0.06 * opacity
},
..badge_color
})),
border: Border {
shape: BorderShape::Continuous,
radius: render.radius(16.0).into(),
..Default::default()
},
..Default::default()
}));
let badge: Element<'_, cosmic::Action<Message>> = if let Some((_, action)) = toggle {
motion::button(
render,
button::custom(badge)
.padding(0)
.name(if enabled { "Turn off" } else { "Turn on" })
.on_press(cosmic::Action::App(Message::Control(action))),
badge_color,
false,
opacity,
)
} else {
badge.into()
};
let summary = row![
badge,
column![
render.text(title).size(14),
render
.text(subtitle)
.size(12)
.class(theme::Text::Color(muted)),
]
.spacing(4)
.width(Length::Fill)
]
.spacing(8)
.align_y(Alignment::Center);
summary.into()
}
pub(super) fn level_meter(
render: crate::rendering::Rendering,
value: u8,
foreground: Color,
opacity: f32,
) -> Element<'static, cosmic::Action<Message>> {
let segment = move |amount: u16, filled: bool| {
container(render.text(""))
.width(Length::FillPortion(amount))
.height(5)
.class(theme::Container::custom(move |_| container::Style {
background: Some(Background::Color(if filled {
foreground
} else {
Color {
a: 0.1 * opacity,
..foreground
}
})),
border: Border {
shape: BorderShape::Continuous,
radius: render.radius(2.5).into(),
..Default::default()
},
..Default::default()
}))
};
let value = u16::from(value.min(100));
let mut meter = row::with_capacity(2).width(Length::Fill);
if value > 0 {
meter = meter.push(segment(value, true));
}
if value < 100 {
meter = meter.push(segment(100 - value, false));
}
meter.into()
}
pub(super) fn control_card<'a>(
render: crate::rendering::Rendering,
content: Element<'a, cosmic::Action<Message>>,
foreground: Color,
opacity: f32,
) -> Element<'a, cosmic::Action<Message>> {
ferese_theme::menus::section(content, foreground, opacity, render.radius(22.))
}
pub(super) fn menu_button<'a>(
render: crate::rendering::Rendering,
label: &'a str,
message: Message,
foreground: Color,
opacity: f32,
) -> Element<'a, cosmic::Action<Message>> {
motion::button(
render,
ferese_theme::menus::button(label, cosmic::Action::App(message), render.font),
foreground,
false,
opacity,
)
}
pub(super) fn shell_switch<'a>(
render: crate::rendering::Rendering,
label: &str,
enabled: bool,
action: Action,
palette: ShellTheme,
opacity: f32,
) -> Element<'a, cosmic::Action<Message>> {
let toggle = ferese_theme::menus::switch(enabled, palette.palette(), opacity);
motion::button(
render,
button::custom(toggle)
.padding(4)
.name(format!("{label}: {}", if enabled { "on" } else { "off" }))
.on_press(cosmic::Action::App(Message::Control(action))),
color(palette.text_primary),
false,
opacity,
)
}
pub(super) fn toggle_row<'a>(
render: crate::rendering::Rendering,
label: &'a str,
on: bool,
action: Action,
palette: ShellTheme,
opacity: f32,
) -> Element<'a, cosmic::Action<Message>> {
ferese_theme::menus::row(
label,
shell_switch(render, label, on, action, palette, opacity),
render.font,
)
}
pub(super) fn slider_row(
render: crate::rendering::Rendering,
source: &'static [u8],
value: u8,
brightness: bool,
foreground: Color,
icon_accent: Color,
opacity: f32,
) -> Element<'static, cosmic::Action<Message>> {
let control = slider(
if brightness { 1..=100 } else { 0..=100 },
value,
move |value| {
cosmic::Action::App(Message::Control(if brightness {
Action::Brightness(value)
} else {
Action::Volume(value)
}))
},
)
.width(Length::Fill)
.height(24)
.class(ferese_theme::menus::slider(foreground, opacity));
row![
accented_icon(source, 18, foreground, icon_accent),
control,
render.text(format!("{value}%")).size(12).width(36)
]
.spacing(8)
.align_y(Alignment::Center)
.into()
}