use rustial_engine::interaction::{InteractionEvent, InteractionEventKind};
use rustial_engine::{
EaseToOptions, FitBoundsOptions, FlyToOptions, GeoBounds, GeoCoord, ListenerId, MapState,
};
use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
pub type LockPoisonedError<T> = PoisonError<T>;
pub struct MapHandle {
inner: RwLock<MapState>,
}
impl MapHandle {
pub fn new(state: MapState) -> Self {
Self {
inner: RwLock::new(state),
}
}
pub fn read(
&self,
) -> Result<RwLockReadGuard<'_, MapState>, LockPoisonedError<RwLockReadGuard<'_, MapState>>>
{
self.inner.read()
}
pub fn write(
&self,
) -> Result<RwLockWriteGuard<'_, MapState>, LockPoisonedError<RwLockWriteGuard<'_, MapState>>>
{
self.inner.write()
}
pub fn fly_to(&self, options: FlyToOptions) {
self.inner
.write()
.expect("MapHandle: lock poisoned")
.fly_to(options);
}
pub fn ease_to(&self, options: EaseToOptions) {
self.inner
.write()
.expect("MapHandle: lock poisoned")
.ease_to(options);
}
pub fn jump_to(&self, target: GeoCoord, distance: f64, pitch: Option<f64>, yaw: Option<f64>) {
self.inner
.write()
.expect("MapHandle: lock poisoned")
.jump_to(target, distance, pitch, yaw);
}
pub fn fit_bounds(&self, bounds: &GeoBounds, options: &FitBoundsOptions) {
self.inner
.write()
.expect("MapHandle: lock poisoned")
.fit_bounds(bounds, options);
}
pub fn geo_to_screen(&self, geo: &GeoCoord) -> Option<(f64, f64)> {
self.inner
.read()
.expect("MapHandle: lock poisoned")
.geo_to_screen(geo)
}
pub fn screen_to_geo(&self, px: f64, py: f64) -> Option<GeoCoord> {
self.inner
.read()
.expect("MapHandle: lock poisoned")
.screen_to_geo(px, py)
}
pub fn zoom_level(&self) -> u8 {
self.inner
.read()
.expect("MapHandle: lock poisoned")
.zoom_level()
}
pub fn on<F>(&self, kind: InteractionEventKind, callback: F) -> ListenerId
where
F: Fn(&InteractionEvent) + Send + Sync + 'static,
{
self.inner
.write()
.expect("MapHandle: lock poisoned")
.on(kind, callback)
}
pub fn once<F>(&self, kind: InteractionEventKind, callback: F) -> ListenerId
where
F: Fn(&InteractionEvent) + Send + Sync + 'static,
{
self.inner
.write()
.expect("MapHandle: lock poisoned")
.once(kind, callback)
}
pub fn off(&self, id: ListenerId) -> bool {
self.inner
.write()
.expect("MapHandle: lock poisoned")
.off(id)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn read_write() {
let handle = MapHandle::new(MapState::new());
{
let state = handle.read().expect("read");
assert_eq!(state.zoom_level(), 0);
}
{
let mut state = handle.write().expect("write");
state.update();
}
}
#[test]
fn multiple_readers() {
let handle = MapHandle::new(MapState::new());
let r1 = handle.read().expect("read 1");
let r2 = handle.read().expect("read 2");
assert_eq!(r1.zoom_level(), r2.zoom_level());
}
}