Use cosmic::Application/cosmic::app::applet
This saves a bit of duplicated boilerplate. Applets seem to work fairly well with this. Though we should see if any other changes to initial window settings are needed in certain applets for the exact behavior we want.
This commit is contained in:
parent
3ad64df5f3
commit
a23f181b7f
28 changed files with 2029 additions and 2597 deletions
|
|
@ -10,19 +10,18 @@ use crate::upower_device::{device_subscription, DeviceDbusEvent};
|
|||
use crate::upower_kbdbacklight::{
|
||||
kbd_backlight_subscription, KeyboardBacklightRequest, KeyboardBacklightUpdate,
|
||||
};
|
||||
use cosmic::app::{applet::applet_button_theme, Command};
|
||||
use cosmic::iced::alignment::Horizontal;
|
||||
use cosmic::iced::wayland::popup::{destroy_popup, get_popup};
|
||||
use cosmic::iced::Color;
|
||||
use cosmic::iced::{
|
||||
widget::{column, container, row, slider, text},
|
||||
window, Alignment, Application, Command, Length, Subscription,
|
||||
window, Alignment, Length, Subscription,
|
||||
};
|
||||
use cosmic::iced_runtime::core::layout::Limits;
|
||||
use cosmic::iced_style::application::{self, Appearance};
|
||||
use cosmic::iced_style::application;
|
||||
use cosmic::theme::Svg;
|
||||
use cosmic::widget::{button, divider, icon};
|
||||
use cosmic::{Element, Theme};
|
||||
use cosmic_applet::{applet_button_theme, CosmicAppletHelper};
|
||||
use cosmic_time::{anim, chain, id, once_cell::sync::Lazy, Instant, Timeline};
|
||||
|
||||
use log::error;
|
||||
|
|
@ -46,17 +45,16 @@ fn format_duration(duration: Duration) -> String {
|
|||
}
|
||||
|
||||
pub fn run() -> cosmic::iced::Result {
|
||||
let helper = CosmicAppletHelper::default();
|
||||
CosmicBatteryApplet::run(helper.window_settings())
|
||||
cosmic::app::applet::run::<CosmicBatteryApplet>(false, ())
|
||||
}
|
||||
|
||||
static MAX_CHARGE: Lazy<id::Toggler> = Lazy::new(id::Toggler::unique);
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct CosmicBatteryApplet {
|
||||
core: cosmic::app::Core,
|
||||
icon_name: String,
|
||||
display_icon_name: String,
|
||||
theme: Theme,
|
||||
charging_limit: bool,
|
||||
battery_percent: f64,
|
||||
on_battery: bool,
|
||||
|
|
@ -67,7 +65,6 @@ struct CosmicBatteryApplet {
|
|||
id_ctr: u128,
|
||||
screen_sender: Option<UnboundedSender<ScreenBacklightRequest>>,
|
||||
kbd_sender: Option<UnboundedSender<KeyboardBacklightRequest>>,
|
||||
applet_helper: CosmicAppletHelper,
|
||||
power_profile: Power,
|
||||
power_profile_sender: Option<UnboundedSender<PowerProfileRequest>>,
|
||||
timeline: Timeline,
|
||||
|
|
@ -144,37 +141,36 @@ enum Message {
|
|||
InitKbdBacklight(UnboundedSender<KeyboardBacklightRequest>, f64),
|
||||
InitScreenBacklight(UnboundedSender<ScreenBacklightRequest>, f64),
|
||||
Errored(String),
|
||||
Ignore,
|
||||
InitProfile(UnboundedSender<PowerProfileRequest>, Power),
|
||||
Profile(Power),
|
||||
SelectProfile(Power),
|
||||
Frame(Instant),
|
||||
Theme(Theme),
|
||||
}
|
||||
|
||||
impl Application for CosmicBatteryApplet {
|
||||
impl cosmic::Application for CosmicBatteryApplet {
|
||||
type Message = Message;
|
||||
type Theme = Theme;
|
||||
type Executor = cosmic::SingleThreadExecutor;
|
||||
type Flags = ();
|
||||
const APP_ID: &'static str = config::APP_ID;
|
||||
|
||||
fn new(_flags: ()) -> (Self, Command<Message>) {
|
||||
let applet_helper = CosmicAppletHelper::default();
|
||||
let theme = applet_helper.theme();
|
||||
fn init(core: cosmic::app::Core, _flags: ()) -> (Self, Command<Message>) {
|
||||
(
|
||||
CosmicBatteryApplet {
|
||||
core,
|
||||
icon_name: "battery-symbolic".to_string(),
|
||||
display_icon_name: "display-brightness-symbolic".to_string(),
|
||||
applet_helper,
|
||||
theme,
|
||||
..Default::default()
|
||||
},
|
||||
Command::none(),
|
||||
)
|
||||
}
|
||||
|
||||
fn title(&self) -> String {
|
||||
config::APP_ID.to_string()
|
||||
fn core(&self) -> &cosmic::app::Core {
|
||||
&self.core
|
||||
}
|
||||
|
||||
fn core_mut(&mut self) -> &mut cosmic::app::Core {
|
||||
&mut self.core
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Message) -> Command<Message> {
|
||||
|
|
@ -217,7 +213,7 @@ impl Application for CosmicBatteryApplet {
|
|||
let new_id = window::Id(self.id_ctr);
|
||||
self.popup.replace(new_id);
|
||||
|
||||
let mut popup_settings = self.applet_helper.get_popup_settings(
|
||||
let mut popup_settings = self.core.applet_helper.get_popup_settings(
|
||||
window::Id(0),
|
||||
new_id,
|
||||
None,
|
||||
|
|
@ -246,7 +242,6 @@ impl Application for CosmicBatteryApplet {
|
|||
Message::UpdateKbdBrightness(b) => {
|
||||
self.kbd_brightness = b;
|
||||
}
|
||||
Message::Ignore => {}
|
||||
Message::InitKbdBacklight(tx, brightness) => {
|
||||
let _ = tx.send(KeyboardBacklightRequest::Get);
|
||||
self.kbd_sender = Some(tx);
|
||||
|
|
@ -278,171 +273,170 @@ impl Application for CosmicBatteryApplet {
|
|||
let _ = tx.send(PowerProfileRequest::Set(profile));
|
||||
}
|
||||
}
|
||||
Message::Theme(t) => {
|
||||
self.theme = t;
|
||||
}
|
||||
}
|
||||
Command::none()
|
||||
}
|
||||
fn view(&self, id: window::Id) -> Element<Message> {
|
||||
if id == window::Id(0) {
|
||||
self.applet_helper
|
||||
.icon_button(&self.icon_name)
|
||||
.on_press(Message::TogglePopup)
|
||||
.into()
|
||||
|
||||
fn view(&self) -> Element<Message> {
|
||||
self.core
|
||||
.applet_helper
|
||||
.icon_button(&self.icon_name)
|
||||
.on_press(Message::TogglePopup)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn view_window(&self, _id: window::Id) -> Element<Message> {
|
||||
let name = text(fl!("battery")).size(14);
|
||||
let description = text(if !self.on_battery {
|
||||
format!("{}%", self.battery_percent)
|
||||
} else {
|
||||
let name = text(fl!("battery")).size(14);
|
||||
let description = text(if !self.on_battery {
|
||||
format!("{}%", self.battery_percent)
|
||||
} else {
|
||||
format!(
|
||||
"{} {} ({:.0}%)",
|
||||
format_duration(self.time_remaining),
|
||||
fl!("until-empty"),
|
||||
self.battery_percent
|
||||
)
|
||||
})
|
||||
.size(10);
|
||||
self.applet_helper
|
||||
.popup_container(
|
||||
column![
|
||||
row![
|
||||
icon(&*self.icon_name, 24).style(Svg::Symbolic),
|
||||
column![name, description]
|
||||
]
|
||||
.padding([0, 24])
|
||||
.spacing(8)
|
||||
.align_items(Alignment::Center),
|
||||
container(divider::horizontal::light())
|
||||
.width(Length::Fill)
|
||||
.padding([0, 12]),
|
||||
button(applet_button_theme())
|
||||
.custom(vec![row![
|
||||
column![
|
||||
text(fl!("battery")).size(14),
|
||||
text(fl!("battery-desc")).size(10)
|
||||
]
|
||||
.width(Length::Fill),
|
||||
icon("emblem-ok-symbolic", 12).size(12).style(
|
||||
match self.power_profile {
|
||||
Power::Battery => Svg::SymbolicActive,
|
||||
_ => Svg::Default,
|
||||
}
|
||||
),
|
||||
]
|
||||
.align_items(Alignment::Center)
|
||||
.into()])
|
||||
.padding([8, 24])
|
||||
.on_press(Message::SelectProfile(Power::Battery))
|
||||
.width(Length::Fill),
|
||||
button(applet_button_theme())
|
||||
.custom(vec![row![
|
||||
column![
|
||||
text(fl!("balanced")).size(14),
|
||||
text(fl!("balanced-desc")).size(10)
|
||||
]
|
||||
.width(Length::Fill),
|
||||
icon("emblem-ok-symbolic", 12).size(12).style(
|
||||
match self.power_profile {
|
||||
Power::Balanced => Svg::SymbolicActive,
|
||||
_ => Svg::Default,
|
||||
}
|
||||
),
|
||||
]
|
||||
.align_items(Alignment::Center)
|
||||
.into()])
|
||||
.padding([8, 24])
|
||||
.on_press(Message::SelectProfile(Power::Balanced))
|
||||
.width(Length::Fill),
|
||||
button(applet_button_theme())
|
||||
.custom(vec![row![
|
||||
column![
|
||||
text(fl!("performance")).size(14),
|
||||
text(fl!("performance-desc")).size(10)
|
||||
]
|
||||
.width(Length::Fill),
|
||||
icon("emblem-ok-symbolic", 12).size(12).style(
|
||||
match self.power_profile {
|
||||
Power::Performance => Svg::SymbolicActive,
|
||||
_ => Svg::Default,
|
||||
}
|
||||
),
|
||||
]
|
||||
.align_items(Alignment::Center)
|
||||
.into()])
|
||||
.padding([8, 24])
|
||||
.on_press(Message::SelectProfile(Power::Performance))
|
||||
.width(Length::Fill),
|
||||
container(divider::horizontal::light())
|
||||
.width(Length::Fill)
|
||||
.padding([0, 12]),
|
||||
container(
|
||||
anim!(
|
||||
//toggler
|
||||
MAX_CHARGE,
|
||||
&self.timeline,
|
||||
fl!("max-charge"),
|
||||
self.charging_limit,
|
||||
Message::SetChargingLimit,
|
||||
)
|
||||
.text_size(14)
|
||||
.width(Length::Fill)
|
||||
)
|
||||
.padding([0, 24])
|
||||
.width(Length::Fill),
|
||||
container(divider::horizontal::light())
|
||||
.width(Length::Fill)
|
||||
.padding([0, 12]),
|
||||
row![
|
||||
icon(self.display_icon_name.as_str(), 24).style(Svg::Symbolic),
|
||||
slider(
|
||||
1..=100,
|
||||
(self.screen_brightness * 100.0) as i32,
|
||||
Message::SetScreenBrightness
|
||||
),
|
||||
text(format!("{:.0}%", self.screen_brightness * 100.0))
|
||||
.size(16)
|
||||
.width(Length::Fixed(40.0))
|
||||
.horizontal_alignment(Horizontal::Right)
|
||||
]
|
||||
.padding([0, 24])
|
||||
.spacing(12),
|
||||
row![
|
||||
icon("keyboard-brightness-symbolic", 24).style(Svg::Symbolic),
|
||||
slider(
|
||||
0..=100,
|
||||
(self.kbd_brightness * 100.0) as i32,
|
||||
Message::SetKbdBrightness
|
||||
),
|
||||
text(format!("{:.0}%", self.kbd_brightness * 100.0))
|
||||
.size(16)
|
||||
.width(Length::Fixed(40.0))
|
||||
.horizontal_alignment(Horizontal::Right)
|
||||
]
|
||||
.padding([0, 24])
|
||||
.spacing(12),
|
||||
container(divider::horizontal::light())
|
||||
.width(Length::Fill)
|
||||
.padding([0, 12]),
|
||||
button(applet_button_theme())
|
||||
.custom(vec![text(fl!("power-settings"))
|
||||
.size(14)
|
||||
.width(Length::Fill)
|
||||
.into()])
|
||||
.on_press(Message::OpenBatterySettings)
|
||||
.width(Length::Fill)
|
||||
.padding([8, 24])
|
||||
format!(
|
||||
"{} {} ({:.0}%)",
|
||||
format_duration(self.time_remaining),
|
||||
fl!("until-empty"),
|
||||
self.battery_percent
|
||||
)
|
||||
})
|
||||
.size(10);
|
||||
self.core
|
||||
.applet_helper
|
||||
.popup_container(
|
||||
column![
|
||||
row![
|
||||
icon(&*self.icon_name, 24).style(Svg::Symbolic),
|
||||
column![name, description]
|
||||
]
|
||||
.padding([0, 24])
|
||||
.spacing(8)
|
||||
.padding([8, 0]),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
.align_items(Alignment::Center),
|
||||
container(divider::horizontal::light())
|
||||
.width(Length::Fill)
|
||||
.padding([0, 12]),
|
||||
button(applet_button_theme())
|
||||
.custom(vec![row![
|
||||
column![
|
||||
text(fl!("battery")).size(14),
|
||||
text(fl!("battery-desc")).size(10)
|
||||
]
|
||||
.width(Length::Fill),
|
||||
icon("emblem-ok-symbolic", 12).size(12).style(
|
||||
match self.power_profile {
|
||||
Power::Battery => Svg::SymbolicActive,
|
||||
_ => Svg::Default,
|
||||
}
|
||||
),
|
||||
]
|
||||
.align_items(Alignment::Center)
|
||||
.into()])
|
||||
.padding([8, 24])
|
||||
.on_press(Message::SelectProfile(Power::Battery))
|
||||
.width(Length::Fill),
|
||||
button(applet_button_theme())
|
||||
.custom(vec![row![
|
||||
column![
|
||||
text(fl!("balanced")).size(14),
|
||||
text(fl!("balanced-desc")).size(10)
|
||||
]
|
||||
.width(Length::Fill),
|
||||
icon("emblem-ok-symbolic", 12).size(12).style(
|
||||
match self.power_profile {
|
||||
Power::Balanced => Svg::SymbolicActive,
|
||||
_ => Svg::Default,
|
||||
}
|
||||
),
|
||||
]
|
||||
.align_items(Alignment::Center)
|
||||
.into()])
|
||||
.padding([8, 24])
|
||||
.on_press(Message::SelectProfile(Power::Balanced))
|
||||
.width(Length::Fill),
|
||||
button(applet_button_theme())
|
||||
.custom(vec![row![
|
||||
column![
|
||||
text(fl!("performance")).size(14),
|
||||
text(fl!("performance-desc")).size(10)
|
||||
]
|
||||
.width(Length::Fill),
|
||||
icon("emblem-ok-symbolic", 12).size(12).style(
|
||||
match self.power_profile {
|
||||
Power::Performance => Svg::SymbolicActive,
|
||||
_ => Svg::Default,
|
||||
}
|
||||
),
|
||||
]
|
||||
.align_items(Alignment::Center)
|
||||
.into()])
|
||||
.padding([8, 24])
|
||||
.on_press(Message::SelectProfile(Power::Performance))
|
||||
.width(Length::Fill),
|
||||
container(divider::horizontal::light())
|
||||
.width(Length::Fill)
|
||||
.padding([0, 12]),
|
||||
container(
|
||||
anim!(
|
||||
//toggler
|
||||
MAX_CHARGE,
|
||||
&self.timeline,
|
||||
fl!("max-charge"),
|
||||
self.charging_limit,
|
||||
Message::SetChargingLimit,
|
||||
)
|
||||
.text_size(14)
|
||||
.width(Length::Fill)
|
||||
)
|
||||
.padding([0, 24])
|
||||
.width(Length::Fill),
|
||||
container(divider::horizontal::light())
|
||||
.width(Length::Fill)
|
||||
.padding([0, 12]),
|
||||
row![
|
||||
icon(self.display_icon_name.as_str(), 24).style(Svg::Symbolic),
|
||||
slider(
|
||||
1..=100,
|
||||
(self.screen_brightness * 100.0) as i32,
|
||||
Message::SetScreenBrightness
|
||||
),
|
||||
text(format!("{:.0}%", self.screen_brightness * 100.0))
|
||||
.size(16)
|
||||
.width(Length::Fixed(40.0))
|
||||
.horizontal_alignment(Horizontal::Right)
|
||||
]
|
||||
.padding([0, 24])
|
||||
.spacing(12),
|
||||
row![
|
||||
icon("keyboard-brightness-symbolic", 24).style(Svg::Symbolic),
|
||||
slider(
|
||||
0..=100,
|
||||
(self.kbd_brightness * 100.0) as i32,
|
||||
Message::SetKbdBrightness
|
||||
),
|
||||
text(format!("{:.0}%", self.kbd_brightness * 100.0))
|
||||
.size(16)
|
||||
.width(Length::Fixed(40.0))
|
||||
.horizontal_alignment(Horizontal::Right)
|
||||
]
|
||||
.padding([0, 24])
|
||||
.spacing(12),
|
||||
container(divider::horizontal::light())
|
||||
.width(Length::Fill)
|
||||
.padding([0, 12]),
|
||||
button(applet_button_theme())
|
||||
.custom(vec![text(fl!("power-settings"))
|
||||
.size(14)
|
||||
.width(Length::Fill)
|
||||
.into()])
|
||||
.on_press(Message::OpenBatterySettings)
|
||||
.width(Length::Fill)
|
||||
.padding([8, 24])
|
||||
]
|
||||
.spacing(8)
|
||||
.padding([8, 0]),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn subscription(&self) -> Subscription<Message> {
|
||||
Subscription::batch(vec![
|
||||
self.applet_helper.theme_subscription(0).map(Message::Theme),
|
||||
device_subscription(0).map(
|
||||
|DeviceDbusEvent::Update {
|
||||
on_battery,
|
||||
|
|
@ -473,18 +467,7 @@ impl Application for CosmicBatteryApplet {
|
|||
])
|
||||
}
|
||||
|
||||
fn theme(&self) -> Theme {
|
||||
self.theme.clone()
|
||||
}
|
||||
|
||||
fn close_requested(&self, _id: window::Id) -> Message {
|
||||
Message::Ignore
|
||||
}
|
||||
|
||||
fn style(&self) -> <Self::Theme as application::StyleSheet>::Style {
|
||||
<Self::Theme as application::StyleSheet>::Style::Custom(Box::new(|theme| Appearance {
|
||||
background_color: Color::from_rgba(0.0, 0.0, 0.0, 0.0),
|
||||
text_color: theme.cosmic().on_bg_color().into(),
|
||||
}))
|
||||
fn style(&self) -> Option<<Theme as application::StyleSheet>::Style> {
|
||||
Some(cosmic::app::applet::style())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue