use egui::{Color32, FontSelection, RichText, Ui};
use egui_phosphor_icons::icons;
use emath::Align;
use epaint::text::LayoutJob;
#[cfg(not(target_arch = "wasm32"))]
use std::sync::atomic::{AtomicU32, Ordering::Relaxed};
#[cfg(not(target_arch = "wasm32"))]
static LOCAL: AtomicU32 = AtomicU32::new(f32::NAN.to_bits());
const WARM: f32 = 80.0;
const HOT: f32 = 85.0;
#[cfg(not(target_arch = "wasm32"))]
pub fn start_local_thread() {
std::thread::Builder::new()
.name("gled:ui:temperature".to_owned())
.spawn(|| {
#[cfg(feature = "profiling")]
profiling::register_thread!("temperature");
loop {
let hottest = sysinfo::Components::new_with_refreshed_list()
.iter()
.filter_map(|component| component.temperature())
.filter(|temperature| temperature.is_finite())
.reduce(f32::max);
LOCAL.store(hottest.unwrap_or(f32::NAN).to_bits(), Relaxed);
std::thread::sleep(std::time::Duration::from_secs(1));
}
})
.expect("Could not spawn temperature thread");
}
pub(crate) fn local() -> Option<f32> {
#[cfg(not(target_arch = "wasm32"))]
{
let celsius = f32::from_bits(LOCAL.load(Relaxed));
(!celsius.is_nan()).then_some(celsius)
}
#[cfg(target_arch = "wasm32")]
None
}
pub(crate) fn temperature(ui: &Ui, name: Option<&str>, celsius: f32) -> LayoutJob {
let mut job = LayoutJob::default();
icons::THERMOMETER.regular().append_to(
&mut job,
ui.style(),
FontSelection::Default,
Align::Center,
);
let text = match name {
Some(name) => format!(" {name} {celsius:.0}°C"),
None => format!(" {celsius:.0}°C"),
};
RichText::new(text).size(14.0).append_to(
&mut job,
ui.style(),
FontSelection::Default,
Align::Center,
);
let color = match celsius {
c if c >= HOT => Some(Color32::RED),
c if c >= WARM => Some(Color32::ORANGE),
_ => None,
};
if let Some(color) = color {
for section in &mut job.sections {
section.format.color = color;
}
}
job
}