use std::cell::*;
use std::rc::*;
use orbclient::{Renderer, Window};
use crate::color::*;
use crate::event_reader::*;
static INITIAL_INSTANT: once_cell::sync::OnceCell<instant::Instant> =
once_cell::sync::OnceCell::new();
#[derive(Clone, Default, Debug)]
pub struct Config {
x: Option<i32>,
y: Option<i32>,
width: u32,
height: u32,
title: String,
events_async: bool,
resizable: bool,
borderless: bool,
uncloseable: bool,
}
impl Config {
pub fn x(mut self, x: i32) -> Self {
self.x = Some(x);
self
}
pub fn y(mut self, y: i32) -> Self {
self.y = Some(y);
self
}
pub fn width(mut self, width: u32) -> Self {
self.width = width;
self
}
pub fn height(mut self, height: u32) -> Self {
self.height = height;
self
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = title.into();
self
}
pub fn events_async(mut self, events_async: bool) -> Self {
self.events_async = events_async;
self
}
pub fn resizable(mut self, resizable: bool) -> Self {
self.resizable = resizable;
self
}
pub fn borderless(mut self, borderless: bool) -> Self {
self.borderless = borderless;
self
}
pub fn uncloseable(mut self, uncloseable: bool) -> Self {
self.uncloseable = uncloseable;
self
}
}
impl From<Config> for OrbClientPlatform {
fn from(config: Config) -> Self {
let mut flags = vec![];
if config.events_async {
flags.push(orbclient::WindowFlag::Async);
}
if config.resizable {
flags.push(orbclient::WindowFlag::Resizable);
}
if config.borderless {
flags.push(orbclient::WindowFlag::Borderless);
}
if config.uncloseable {
flags.push(orbclient::WindowFlag::Unclosable);
}
let x = if let Some(x) = config.x {
x
} else {
orbclient::get_display_size().map_or(0, |s| (s.0 - config.width) / 2) as i32
};
let y = if let Some(y) = config.y {
y
} else {
orbclient::get_display_size().map_or(0, |s| (s.1 - config.height) / 2) as i32
};
Self {
slint_window: core::cell::RefCell::new(
slint::platform::software_renderer::MinimalSoftwareWindow::new(),
),
orb_window: RefCell::new(
Window::new_flags(x, y, config.width, config.height, &config.title, &flags)
.unwrap(),
),
event_reader: EventReader::default(),
}
}
}
pub struct OrbClientPlatform {
slint_window: RefCell<Rc<slint::platform::software_renderer::MinimalSoftwareWindow<1>>>,
orb_window: RefCell<Window>,
event_reader: EventReader,
}
impl OrbClientPlatform {
pub fn new() -> Self {
Config::default()
.width(600)
.height(400)
.title("Slint orbclient window")
.into()
}
}
impl Default for OrbClientPlatform {
fn default() -> Self {
OrbClientPlatform::new()
}
}
impl slint::platform::Platform for OrbClientPlatform {
fn create_window_adapter(&self) -> Rc<dyn slint::platform::WindowAdapter> {
self.slint_window.borrow().clone()
}
fn set_clipboard_text(&self, text: &str) {
self.orb_window.borrow_mut().set_clipboard(text);
}
fn clipboard_text(&self) -> Option<String> {
Some(self.orb_window.borrow().clipboard())
}
fn duration_since_start(&self) -> core::time::Duration {
let the_beginning = *INITIAL_INSTANT.get_or_init(instant::Instant::now);
instant::Instant::now() - the_beginning
}
fn run_event_loop(&self) {
let width = self.orb_window.borrow().width();
let height = self.orb_window.borrow().height();
self.slint_window
.borrow()
.as_ref()
.set_size(slint::PhysicalSize::new(width, height));
let mut work_buffer = vec![Color(0); width as usize * height as usize];
'events: loop {
slint::platform::update_timers_and_animations();
self.slint_window.borrow().draw_if_needed(|renderer| {
renderer.render(
&mut work_buffer,
self.slint_window.borrow().size().width as usize,
);
unsafe {
core::ptr::copy(
work_buffer.as_ptr(),
self.orb_window.borrow_mut().data_mut().as_mut_ptr() as *mut Color,
work_buffer.len(),
);
};
self.orb_window.borrow_mut().sync();
});
for event in self.event_reader.read(&mut self.orb_window.borrow_mut()) {
match event {
Event::WindowEvent(e) => self.slint_window.borrow().dispatch_event(e),
Event::Resize(s) => {
self.slint_window.borrow().set_size(s);
work_buffer.resize(s.width as usize * s.height as usize, Color(0));
}
Event::Quit => break 'events,
}
}
}
}
}