acid/firmware/acid-firmware/src/ui/window_adapter.rs
2026-01-22 01:22:31 +01:00

96 lines
2.6 KiB
Rust

use core::{
cell::Cell,
ops::{Deref, DerefMut},
};
use alloc::rc::{Rc, Weak};
use slint::{
PhysicalSize, Window, WindowSize,
platform::{Renderer, WindowAdapter, WindowEvent, software_renderer::SoftwareRenderer},
};
/// This is a minimal adapter for a Window that doesn't have any other feature than rendering
/// using the software renderer.
pub struct SoftwareWindowAdapter {
pub window: Window,
pub renderer: SoftwareRenderer,
needs_redraw: Cell<bool>,
size: Cell<PhysicalSize>,
}
impl SoftwareWindowAdapter {
/// Instantiate a new MinimalWindowAdaptor
///
/// The `repaint_buffer_type` parameter specify what kind of buffer are passed to the [`SoftwareRenderer`]
pub fn new(renderer: SoftwareRenderer) -> Rc<Self> {
Rc::new_cyclic(|w: &Weak<Self>| Self {
window: Window::new(w.clone()),
renderer,
needs_redraw: Cell::new(true),
size: Default::default(),
})
}
/// If the window needs to be redrawn, the callback will be called with the
/// [renderer](SoftwareRenderer) that should be used to do the drawing.
///
/// [`SoftwareRenderer::render()`] or [`SoftwareRenderer::render_by_line()`] should be called
/// in that callback.
///
/// Return true if something was redrawn.
pub fn draw_if_needed(&self, render_callback: impl FnOnce(&SoftwareRenderer)) -> bool {
if self.needs_redraw.replace(false)
/*|| self.renderer.rendering_metrics_collector.is_some()*/
{
render_callback(&self.renderer);
true
} else {
false
}
}
// pub fn set_scale_factor(&self, scale_factor: f32) {
// self.window.dispatch_event(WindowEvent::ScaleFactorChanged { scale_factor });
// }
}
impl WindowAdapter for SoftwareWindowAdapter {
fn window(&self) -> &Window {
&self.window
}
fn renderer(&self) -> &dyn Renderer {
&self.renderer
}
fn size(&self) -> PhysicalSize {
self.size.get()
}
fn set_size(&self, size: WindowSize) {
let sf = self.window.scale_factor();
self.size.set(size.to_physical(sf));
self.window.dispatch_event(WindowEvent::Resized {
size: size.to_logical(sf),
})
}
fn request_redraw(&self) {
self.needs_redraw.set(true);
}
}
impl Deref for SoftwareWindowAdapter {
type Target = Window;
fn deref(&self) -> &Self::Target {
&self.window
}
}
impl DerefMut for SoftwareWindowAdapter {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.window
}
}