feat(bar): add cpu widget

This commit adds a CPU widget, following the patterns of the Memory
widget.
This commit is contained in:
Csaba
2024-10-08 19:02:55 +02:00
committed by LGUG2Z
parent 3489163793
commit a9e98034b0
3 changed files with 112 additions and 0 deletions

107
komorebi-bar/src/cpu.rs Normal file
View File

@@ -0,0 +1,107 @@
use crate::widget::BarWidget;
use crate::WIDGET_SPACING;
use eframe::egui::text::LayoutJob;
use eframe::egui::Context;
use eframe::egui::FontId;
use eframe::egui::Label;
use eframe::egui::Sense;
use eframe::egui::TextFormat;
use eframe::egui::TextStyle;
use eframe::egui::Ui;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
use std::process::Command;
use std::time::Duration;
use std::time::Instant;
use sysinfo::RefreshKind;
use sysinfo::System;
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
pub struct CpuConfig {
/// Enable the Cpu widget
pub enable: bool,
/// Data refresh interval (default: 10 seconds)
pub data_refresh_interval: Option<u64>,
}
impl From<CpuConfig> for Cpu {
fn from(value: CpuConfig) -> Self {
let mut system =
System::new_with_specifics(RefreshKind::default().without_memory().without_processes());
system.refresh_cpu_usage();
Self {
enable: value.enable,
system,
data_refresh_interval: value.data_refresh_interval.unwrap_or(10),
last_updated: Instant::now(),
}
}
}
pub struct Cpu {
pub enable: bool,
system: System,
data_refresh_interval: u64,
last_updated: Instant,
}
impl Cpu {
fn output(&mut self) -> String {
let now = Instant::now();
if now.duration_since(self.last_updated) > Duration::from_secs(self.data_refresh_interval) {
self.system.refresh_cpu_usage();
self.last_updated = now;
}
let used = self.system.global_cpu_usage();
format!("CPU: {:.0}%", used)
}
}
impl BarWidget for Cpu {
fn render(&mut self, ctx: &Context, ui: &mut Ui) {
if self.enable {
let output = self.output();
if !output.is_empty() {
let font_id = ctx
.style()
.text_styles
.get(&TextStyle::Body)
.cloned()
.unwrap_or_else(FontId::default);
let mut layout_job = LayoutJob::simple(
egui_phosphor::regular::CIRCUITRY.to_string(),
font_id.clone(),
ctx.style().visuals.selection.stroke.color,
100.0,
);
layout_job.append(
&output,
10.0,
TextFormat::simple(font_id, ctx.style().visuals.text_color()),
);
if ui
.add(
Label::new(layout_job)
.selectable(false)
.sense(Sense::click()),
)
.clicked()
{
if let Err(error) = Command::new("cmd.exe").args(["/C", "taskmgr.exe"]).spawn()
{
eprintln!("{}", error)
}
}
}
ui.add_space(WIDGET_SPACING);
}
}
}

View File

@@ -1,4 +1,5 @@
mod bar;
mod cpu;
mod battery;
mod config;
mod date;

View File

@@ -1,5 +1,7 @@
use crate::battery::Battery;
use crate::battery::BatteryConfig;
use crate::cpu::Cpu;
use crate::cpu::CpuConfig;
use crate::date::Date;
use crate::date::DateConfig;
use crate::komorebi::Komorebi;
@@ -27,6 +29,7 @@ pub trait BarWidget {
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
pub enum WidgetConfig {
Battery(BatteryConfig),
Cpu(CpuConfig),
Date(DateConfig),
Komorebi(KomorebiConfig),
Media(MediaConfig),
@@ -40,6 +43,7 @@ impl WidgetConfig {
pub fn as_boxed_bar_widget(&self) -> Box<dyn BarWidget> {
match self {
WidgetConfig::Battery(config) => Box::new(Battery::from(*config)),
WidgetConfig::Cpu(config) => Box::new(Cpu::from(*config)),
WidgetConfig::Date(config) => Box::new(Date::from(config.clone())),
WidgetConfig::Komorebi(config) => Box::new(Komorebi::from(config)),
WidgetConfig::Media(config) => Box::new(Media::from(*config)),