use leaflet::Map;
use leptos::prelude::*;
use wasm_bindgen::JsCast;
use crate::core::{JsReadSignal, JsRwSignal, JsWriteSignal};
#[derive(Debug, Clone, Copy)]
pub struct LeafletMapContext {
map: JsRwSignal<Option<leaflet::Map>>,
thread_id: std::thread::ThreadId,
}
impl LeafletMapContext {
pub fn new() -> Self {
Self {
map: JsRwSignal::new_local(None),
thread_id: std::thread::current().id(),
}
}
pub fn set_map(&self, map: &leaflet::Map) {
if !self.is_valid() {
leptos::logging::error!("Accessing map from a different thread. Probably running on the server.");
return;
}
self.map.set(Some(map.clone()));
}
pub fn map(&self) -> Option<leaflet::Map> {
if self.is_valid() {
self.map.get()
} else {
leptos::logging::error!("Accessing map from a different thread. Probably running on the server.");
None
}
}
pub fn map_untracked(&self) -> Option<leaflet::Map> {
if self.is_valid() {
self.map.get_untracked()
} else {
leptos::logging::error!("Accessing map from a different thread. Probably running on the server.");
None
}
}
pub fn map_signal(&self) -> JsReadSignal<Option<leaflet::Map>> {
if self.is_valid() {
self.map.read_only()
} else {
panic!("Accessing map from a different thread. Probably running on the server.");
}
}
pub fn add_layer<L: Into<leaflet::Layer> + Clone>(&self, layer: &L) {
if !self.is_valid() {
leptos::logging::error!("Accessing map from a different thread. Probably running on the server.");
return;
}
let map = self.map.get_untracked().expect("Map to be available");
let layer: leaflet::Layer = layer.to_owned().into();
layer.add_to(&map);
}
pub fn remove_layer<L: Into<leaflet::Layer> + Clone>(&self, layer: &L) {
if !self.is_valid() {
leptos::logging::error!("Accessing map from a different thread. Probably running on the server.");
return;
}
let map = self.map.get_untracked().expect("Map to be available");
let layer: leaflet::Layer = layer.to_owned().into();
layer.remove_from(&map);
}
fn is_valid(&self) -> bool {
std::thread::current().id() == self.thread_id && !self.map.is_disposed()
}
}
impl Default for LeafletMapContext {
fn default() -> Self {
Self::new()
}
}
pub fn provide_leaflet_context() -> LeafletMapContext {
let context = LeafletMapContext::new();
provide_context(context);
context
}
pub fn use_leaflet_context() -> Option<LeafletMapContext> {
use_context::<LeafletMapContext>()
}
pub fn extend_context_with_overlay() -> LeafletOverlayContainerContext {
let overlay_context = LeafletOverlayContainerContext::new();
provide_context(overlay_context);
overlay_context
}
pub fn use_overlay_context() -> Option<LeafletOverlayContainerContext> {
use_context::<LeafletOverlayContainerContext>()
}
pub fn use_overlay_context_layer<T>() -> Option<T>
where
T: Into<leaflet::Layer> + Clone + JsCast,
{
expect_context::<LeafletOverlayContainerContext>().container::<T>()
}
pub fn update_overlay_context<C: Into<leaflet::Layer> + Clone>(layer: &C) {
let overlay_context = use_context::<LeafletOverlayContainerContext>().expect("overlay context");
overlay_context.set_container(layer);
}
#[derive(Debug, Clone, Copy)]
pub struct LeafletOverlayContainerContext {
container: JsRwSignal<Option<leaflet::Layer>>,
thread_id: std::thread::ThreadId,
}
impl LeafletOverlayContainerContext {
pub fn new() -> Self {
Self {
container: JsRwSignal::new_local(None),
thread_id: std::thread::current().id(),
}
}
pub fn set_container<C: Into<leaflet::Layer> + Clone>(&self, layer: &C) {
if !self.is_valid() {
leptos::logging::error!("Accessing map from a different thread. Probably running on the server.");
return;
}
self.container.set(Some(layer.clone().into()));
}
pub fn container<T: JsCast>(&self) -> Option<T> {
if !self.is_valid() {
leptos::logging::error!("Accessing map from a different thread. Probably running on the server.");
return None;
}
self.container.get().map(|layer| layer.unchecked_into())
}
pub fn untrack_container<C: JsCast>(&self) -> Option<C> {
if !self.is_valid() {
leptos::logging::error!("Accessing map from a different thread. Probably running on the server.");
return None;
}
self.container
.get_untracked()
.map(|layer| layer.unchecked_into())
}
fn is_valid(&self) -> bool {
std::thread::current().id() == self.thread_id && !self.container.is_disposed()
}
}
impl Default for LeafletOverlayContainerContext {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy)]
pub struct TileLayerWmsContext {
wms: JsRwSignal<Option<leaflet::TileLayerWms>>,
thread_id: std::thread::ThreadId,
}
impl Default for TileLayerWmsContext {
fn default() -> Self {
Self::new()
}
}
impl TileLayerWmsContext {
pub fn new() -> Self {
Self {
wms: JsRwSignal::new_local(None),
thread_id: std::thread::current().id(),
}
}
pub fn set_wms(&self, wms: &leaflet::TileLayerWms) {
if !self.is_valid() {
leptos::logging::error!("Accessing map from a different thread. Probably running on the server.");
return;
}
self.wms.set(Some(wms.clone()));
}
pub fn wms(&self) -> Option<leaflet::TileLayerWms> {
if self.is_valid() {
self.wms.get()
} else {
leptos::logging::error!("Accessing map from a different thread. Probably running on the server.");
None
}
}
fn is_valid(&self) -> bool {
std::thread::current().id() == self.thread_id && !self.wms.is_disposed()
}
}
pub type MapReadSignal = JsReadSignal<Option<Map>>;
pub type MapWriteSignal = JsWriteSignal<Option<Map>>;
pub fn create_map_signal() -> (MapReadSignal, MapWriteSignal) {
JsRwSignal::new_local(None).split()
}