use crate::compat::{format, String};
use crate::core::{ObjectId, PlatformFamily};
use crate::platform::state::{BackendState, WindowStateRecord};
use crate::platform::types::*;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum StubHandleKind {
Window,
}
pub struct StubPlatform {
backend: &'static str,
family: PlatformFamily,
state: BackendState<StubHandleKind>,
pub(crate) ime_bridge: crate::platform::ime::MockImeBridge,
}
impl StubPlatform {
pub fn new(backend: &'static str, family: PlatformFamily) -> Self {
Self {
backend,
family,
state: BackendState::new(),
ime_bridge: crate::platform::ime::MockImeBridge::new(),
}
}
pub fn register_widget(
&self,
widget_id: ObjectId,
text: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) {
self.state.register_widget_with_id(
widget_id,
StubHandleKind::Window,
text,
x,
y,
width,
height,
);
}
pub fn widget_count(&self) -> usize {
self.state.widget_count()
}
}
pub(crate) fn stub_platform_singleton() -> &'static StubPlatform {
use crate::compat::OnceLock;
static HOST: OnceLock<StubPlatform> = OnceLock::new();
HOST.get_or_init(|| StubPlatform::new("portable", PlatformFamily::Embedded))
}
impl Platform for StubPlatform {
crate::impl_platform_state_properties!();
fn supports_surfaces(&self) -> bool {
true
}
fn mount_surface(
&self,
_parent: crate::core::ObjectId,
id: crate::core::ObjectId,
rect: crate::core::Rect,
) -> bool {
self.state.mount_surface_record(id, rect)
}
fn resize_surface(&self, id: crate::core::ObjectId, rect: crate::core::Rect) -> bool {
self.state.resize_surface_record(id, rect)
}
fn unmount_surface(&self, id: crate::core::ObjectId) -> bool {
self.state.unmount_surface_record(id)
}
fn invalidate_surface(&self, id: crate::core::ObjectId) -> bool {
self.state.record_repaint_request(id)
}
fn take_pending_repaint(&self) -> Option<crate::core::ObjectId> {
self.state.take_pending_repaint()
}
fn as_any(&self) -> &dyn core::any::Any {
self
}
fn backend_name(&self) -> &'static str {
self.backend
}
fn family(&self) -> PlatformFamily {
self.family
}
fn total_memory_mb(&self) -> Option<u64> {
None
}
fn is_on_battery(&self) -> bool {
false
}
fn process_memory_utilization(&self) -> Option<f32> {
None
}
fn process_cpu_utilization(&self) -> Option<f32> {
None
}
fn spawn_print_job(&self, _job_file: &std::path::Path) -> Result<(), String> {
Err(format!(
"the stub platform has no print spooler, so job file '{}' was not printed; \
select a real OS backend to print",
_job_file.display()
))
}
fn init(&self) {
log::info!("[stub] StubPlatform init (testing backend)");
}
fn run(&self) {
log::info!("[stub] StubPlatform run (testing backend)");
}
fn quit(&self) {
log::info!("[stub] StubPlatform quit");
}
fn destroy_widget(&self, widget_id: ObjectId) -> bool {
self.state.destroy_widget(widget_id)
}
fn create_window(&self, title: &str, x: i32, y: i32, width: u32, height: u32) -> ObjectId {
let id = self.state.create_widget(StubHandleKind::Window, title, x, y, width, height);
self.state.init_window_state(id, WindowStateRecord::new_window());
id
}
fn poll_menu_triggered(&self) -> Option<ObjectId> {
self.state.pop_menu_event()
}
fn inject_menu_trigger(&self, menu_item_id: ObjectId) -> bool {
if !self.state.contains_widget(menu_item_id) {
return false;
}
self.state.push_menu_event(menu_item_id);
true
}
fn poll_widget_triggered(&self) -> Option<ObjectId> {
self.poll_widget_trigger_event().map(|event| event.widget_id)
}
fn poll_widget_trigger_event(&self) -> Option<WidgetTriggerEvent> {
self.state.pop_widget_event()
}
fn pop_widget_trigger_event_for(&self, widget_id: ObjectId) -> Option<WidgetTriggerEvent> {
self.state.pop_widget_event_for(widget_id)
}
fn inject_widget_trigger_event(&self, widget_id: ObjectId, kind: WidgetTriggerKind) -> bool {
if !self.state.contains_widget(widget_id) {
return false;
}
self.state.push_widget_event(WidgetTriggerEvent { widget_id, kind });
true
}
fn window_client_size(&self, window_id: ObjectId) -> Option<(u32, u32)> {
crate::window_client_size(window_id).or_else(|| self.state.window_size(window_id))
}
fn queue_resize_trigger(&self, window_id: ObjectId, width: u32, height: u32) -> bool {
crate::queue_resize_trigger(window_id, width, height)
}
fn set_clipboard_text(&self, text: &str) -> bool {
self.state.set_clipboard_text(text)
}
fn get_clipboard_text(&self) -> String {
self.state.clipboard_text()
}
fn ime_bridge(&self) -> Option<&dyn crate::platform::ime::ImeBridge> {
Some(&self.ime_bridge)
}
}