use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use yog_gfx::GfxContext;
use crate::layout::Rect;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Pointer {
Down { x: f32, y: f32 },
Drag { x: f32, y: f32 },
Up { x: f32, y: f32 },
Move { x: f32, y: f32 },
Leave,
}
pub trait Surface: Send + Sync {
fn paint(&self, gfx: &GfxContext, rect: Rect);
fn pointer(&self, ev: Pointer, size: (f32, f32)) -> bool {
let _ = (ev, size);
false
}
fn scroll(&self, dy: f32, size: (f32, f32)) -> bool {
let _ = (dy, size);
false
}
}
type Registry = HashMap<String, Arc<dyn Surface>>;
static SURFACES: Mutex<Option<Registry>> = Mutex::new(None);
pub fn register(id: impl Into<String>, surface: Arc<dyn Surface>) {
SURFACES
.lock()
.unwrap_or_else(|e| e.into_inner())
.get_or_insert_with(HashMap::new)
.insert(id.into(), surface);
}
pub fn unregister(id: &str) {
if let Some(map) = SURFACES.lock().unwrap_or_else(|e| e.into_inner()).as_mut() {
map.remove(id);
}
}
pub fn get(id: &str) -> Option<Arc<dyn Surface>> {
SURFACES
.lock()
.unwrap_or_else(|e| e.into_inner())
.as_ref()?
.get(id)
.cloned()
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::atomic::{AtomicU32, Ordering};
struct Counter(AtomicU32);
impl Surface for Counter {
fn paint(&self, _: &GfxContext, _: Rect) {}
fn pointer(&self, _: Pointer, _: (f32, f32)) -> bool {
self.0.fetch_add(1, Ordering::Relaxed);
true
}
}
#[test]
fn registry_finds_by_id() {
assert!(get("test:none").is_none());
let c = Arc::new(Counter(AtomicU32::new(0)));
register("test:counter", c.clone());
let s = get("test:counter").unwrap();
assert!(s.pointer(Pointer::Leave, (1.0, 1.0)));
assert_eq!(c.0.load(Ordering::Relaxed), 1);
unregister("test:counter");
assert!(get("test:counter").is_none());
}
}