step 1: lock public api and pure core
This commit is contained in:
@@ -1,2 +1,87 @@
|
||||
"""Public API for dpg-map."""
|
||||
|
||||
from .api import (
|
||||
add_layer,
|
||||
add_marker,
|
||||
add_polyline,
|
||||
add_trajectory,
|
||||
clear_disk_cache,
|
||||
clear_layer,
|
||||
clear_map,
|
||||
clear_memory_cache,
|
||||
configure,
|
||||
delete_overlay,
|
||||
fit_bounds,
|
||||
get_cache_stats,
|
||||
get_center,
|
||||
get_map_debug_state,
|
||||
get_zoom,
|
||||
hide_layer,
|
||||
latlon_to_screen,
|
||||
screen_to_latlon,
|
||||
set_center,
|
||||
set_marker_label,
|
||||
set_marker_position,
|
||||
set_overlay_show,
|
||||
set_polyline_points,
|
||||
set_provider,
|
||||
set_view,
|
||||
set_zoom,
|
||||
show_layer,
|
||||
update_marker,
|
||||
update_polyline,
|
||||
update_trajectory,
|
||||
)
|
||||
from .providers import (
|
||||
TileProvider,
|
||||
get_provider,
|
||||
list_providers,
|
||||
register_provider,
|
||||
unregister_provider,
|
||||
)
|
||||
from .widget import map_widget
|
||||
|
||||
__all__ = [
|
||||
"TileProvider",
|
||||
"add_layer",
|
||||
"add_marker",
|
||||
"add_polyline",
|
||||
"add_trajectory",
|
||||
"clear_disk_cache",
|
||||
"clear_layer",
|
||||
"clear_map",
|
||||
"clear_memory_cache",
|
||||
"configure",
|
||||
"delete_overlay",
|
||||
"fit_bounds",
|
||||
"get_cache_stats",
|
||||
"get_center",
|
||||
"get_map_debug_state",
|
||||
"get_provider",
|
||||
"get_zoom",
|
||||
"hide_layer",
|
||||
"latlon_to_screen",
|
||||
"list_providers",
|
||||
"map_widget",
|
||||
"register_provider",
|
||||
"screen_to_latlon",
|
||||
"set_center",
|
||||
"set_marker_label",
|
||||
"set_marker_position",
|
||||
"set_overlay_show",
|
||||
"set_polyline_points",
|
||||
"set_provider",
|
||||
"set_view",
|
||||
"set_zoom",
|
||||
"show_layer",
|
||||
"unregister_provider",
|
||||
"update_marker",
|
||||
"update_polyline",
|
||||
"update_trajectory",
|
||||
]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
print("Hello from dpg-map!")
|
||||
"""Console entry point placeholder."""
|
||||
|
||||
print("dpg-map")
|
||||
|
||||
@@ -1 +1,211 @@
|
||||
"""Public API wrappers for dpg-map."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Sequence
|
||||
from pathlib import Path
|
||||
from typing import Any, NoReturn
|
||||
|
||||
from .cache import CacheStats
|
||||
from .exceptions import DpgMapNotImplementedError
|
||||
from .providers import TileProvider
|
||||
from .types import Bounds, LatLon, Point, Tag
|
||||
|
||||
|
||||
def _stub(name: str) -> NoReturn:
|
||||
raise DpgMapNotImplementedError(f"dpg_map.{name} is not implemented until a later rebuild step")
|
||||
|
||||
|
||||
def configure(
|
||||
*,
|
||||
user_agent: str | None = None,
|
||||
cache_dir: str | Path | None = None,
|
||||
default_provider: str | TileProvider = "osm",
|
||||
memory_cache_max_tiles: int = 512,
|
||||
disk_cache_max_bytes: int | None = 2_000_000_000,
|
||||
prefetch_margin_tiles: int = 1,
|
||||
tile_worker_count: int = 4,
|
||||
overlay_update_policy: str = "coalesce",
|
||||
debug: bool = False,
|
||||
) -> None:
|
||||
_stub("configure")
|
||||
|
||||
|
||||
def set_center(lat: float, lon: float, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("set_center")
|
||||
|
||||
|
||||
def get_center(*, map_tag: Tag | None = None) -> LatLon:
|
||||
_stub("get_center")
|
||||
|
||||
|
||||
def set_zoom(zoom: int, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("set_zoom")
|
||||
|
||||
|
||||
def get_zoom(*, map_tag: Tag | None = None) -> int:
|
||||
_stub("get_zoom")
|
||||
|
||||
|
||||
def set_view(
|
||||
*,
|
||||
center: LatLon | None = None,
|
||||
zoom: int | None = None,
|
||||
map_tag: Tag | None = None,
|
||||
) -> None:
|
||||
_stub("set_view")
|
||||
|
||||
|
||||
def fit_bounds(bounds: Bounds, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("fit_bounds")
|
||||
|
||||
|
||||
def screen_to_latlon(x: float, y: float, *, map_tag: Tag | None = None) -> LatLon:
|
||||
_stub("screen_to_latlon")
|
||||
|
||||
|
||||
def latlon_to_screen(lat: float, lon: float, *, map_tag: Tag | None = None) -> Point:
|
||||
_stub("latlon_to_screen")
|
||||
|
||||
|
||||
def add_marker(
|
||||
tag: Tag,
|
||||
*,
|
||||
lat: float,
|
||||
lon: float,
|
||||
label: str | None = None,
|
||||
layer: str = "default",
|
||||
show: bool = True,
|
||||
map_tag: Tag | None = None,
|
||||
**kwargs: Any,
|
||||
) -> Tag:
|
||||
_stub("add_marker")
|
||||
|
||||
|
||||
def add_polyline(
|
||||
tag: Tag,
|
||||
*,
|
||||
points: Sequence[LatLon] | None = None,
|
||||
lats: Sequence[float] | None = None,
|
||||
lons: Sequence[float] | None = None,
|
||||
layer: str = "default",
|
||||
show: bool = True,
|
||||
map_tag: Tag | None = None,
|
||||
**kwargs: Any,
|
||||
) -> Tag:
|
||||
_stub("add_polyline")
|
||||
|
||||
|
||||
def add_trajectory(
|
||||
tag: Tag,
|
||||
*,
|
||||
points: Sequence[LatLon] | None = None,
|
||||
lats: Sequence[float] | None = None,
|
||||
lons: Sequence[float] | None = None,
|
||||
layer: str = "default",
|
||||
show: bool = True,
|
||||
map_tag: Tag | None = None,
|
||||
**kwargs: Any,
|
||||
) -> Tag:
|
||||
_stub("add_trajectory")
|
||||
|
||||
|
||||
def update_marker(
|
||||
tag: Tag,
|
||||
*,
|
||||
lat: float | None = None,
|
||||
lon: float | None = None,
|
||||
label: str | None = None,
|
||||
map_tag: Tag | None = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
_stub("update_marker")
|
||||
|
||||
|
||||
def update_polyline(
|
||||
tag: Tag,
|
||||
*,
|
||||
points: Sequence[LatLon] | None = None,
|
||||
lats: Sequence[float] | None = None,
|
||||
lons: Sequence[float] | None = None,
|
||||
map_tag: Tag | None = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
_stub("update_polyline")
|
||||
|
||||
|
||||
def update_trajectory(
|
||||
tag: Tag,
|
||||
*,
|
||||
points: Sequence[LatLon] | None = None,
|
||||
lats: Sequence[float] | None = None,
|
||||
lons: Sequence[float] | None = None,
|
||||
map_tag: Tag | None = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
_stub("update_trajectory")
|
||||
|
||||
|
||||
def set_marker_position(tag: Tag, lat: float, lon: float, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("set_marker_position")
|
||||
|
||||
|
||||
def set_marker_label(tag: Tag, label: str, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("set_marker_label")
|
||||
|
||||
|
||||
def set_polyline_points(
|
||||
tag: Tag,
|
||||
points: Sequence[LatLon],
|
||||
*,
|
||||
map_tag: Tag | None = None,
|
||||
) -> None:
|
||||
_stub("set_polyline_points")
|
||||
|
||||
|
||||
def set_overlay_show(tag: Tag, show: bool, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("set_overlay_show")
|
||||
|
||||
|
||||
def delete_overlay(tag: Tag, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("delete_overlay")
|
||||
|
||||
|
||||
def add_layer(name: str, *, show: bool = True, map_tag: Tag | None = None) -> None:
|
||||
_stub("add_layer")
|
||||
|
||||
|
||||
def show_layer(name: str, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("show_layer")
|
||||
|
||||
|
||||
def hide_layer(name: str, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("hide_layer")
|
||||
|
||||
|
||||
def clear_layer(name: str, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("clear_layer")
|
||||
|
||||
|
||||
def clear_map(*, map_tag: Tag | None = None) -> None:
|
||||
_stub("clear_map")
|
||||
|
||||
|
||||
def set_provider(provider: str | TileProvider, *, map_tag: Tag | None = None) -> None:
|
||||
_stub("set_provider")
|
||||
|
||||
|
||||
def clear_memory_cache(*, map_tag: Tag | None = None) -> None:
|
||||
_stub("clear_memory_cache")
|
||||
|
||||
|
||||
def clear_disk_cache(*, map_tag: Tag | None = None) -> None:
|
||||
_stub("clear_disk_cache")
|
||||
|
||||
|
||||
def get_cache_stats(*, map_tag: Tag | None = None) -> CacheStats:
|
||||
_stub("get_cache_stats")
|
||||
|
||||
|
||||
def get_map_debug_state(*, map_tag: Tag | None = None) -> dict[str, Any]:
|
||||
_stub("get_map_debug_state")
|
||||
|
||||
@@ -1 +1,36 @@
|
||||
"""Memory and disk cache helpers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class CacheStats:
|
||||
"""Public cache statistics snapshot."""
|
||||
|
||||
memory_tiles: int = 0
|
||||
memory_max_tiles: int = 0
|
||||
memory_hits: int = 0
|
||||
memory_misses: int = 0
|
||||
disk_bytes: int = 0
|
||||
disk_max_bytes: int | None = None
|
||||
disk_hits: int = 0
|
||||
disk_misses: int = 0
|
||||
disk_path: Path | None = None
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class MemoryCacheConfig:
|
||||
"""Initial memory cache configuration."""
|
||||
|
||||
max_tiles: int = 512
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class DiskCacheConfig:
|
||||
"""Initial persistent disk cache configuration."""
|
||||
|
||||
path: Path | None = None
|
||||
max_bytes: int | None = 2_000_000_000
|
||||
|
||||
@@ -1 +1,29 @@
|
||||
"""Public exception types."""
|
||||
"""Public exception types for dpg-map."""
|
||||
|
||||
|
||||
class DpgMapError(Exception):
|
||||
"""Base exception for all public dpg-map errors."""
|
||||
|
||||
|
||||
class DpgMapNotImplementedError(DpgMapError, NotImplementedError):
|
||||
"""Raised by public APIs that are intentionally stubbed during the rebuild."""
|
||||
|
||||
|
||||
class ProviderError(DpgMapError):
|
||||
"""Base exception for tile provider errors."""
|
||||
|
||||
|
||||
class ProviderExistsError(ProviderError):
|
||||
"""Raised when registering a provider name that already exists."""
|
||||
|
||||
|
||||
class ProviderNotFoundError(ProviderError):
|
||||
"""Raised when a requested tile provider is not registered."""
|
||||
|
||||
|
||||
class InvalidProviderError(ProviderError, ValueError):
|
||||
"""Raised when a tile provider definition is invalid."""
|
||||
|
||||
|
||||
class ProjectionError(DpgMapError, ValueError):
|
||||
"""Raised when geographic projection input is invalid."""
|
||||
|
||||
@@ -1 +1,92 @@
|
||||
"""Web Mercator projection helpers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
|
||||
from .exceptions import ProjectionError
|
||||
from .types import LatLon, Point
|
||||
|
||||
WEB_MERCATOR_MAX_LAT = 85.05112878
|
||||
DEFAULT_TILE_SIZE = 256
|
||||
|
||||
|
||||
def clamp_latitude(lat: float) -> float:
|
||||
"""Clamp latitude to the Web Mercator representable range."""
|
||||
|
||||
return min(max(lat, -WEB_MERCATOR_MAX_LAT), WEB_MERCATOR_MAX_LAT)
|
||||
|
||||
|
||||
def map_size(zoom: int, tile_size: int = DEFAULT_TILE_SIZE) -> int:
|
||||
"""Return square pixel size of the full world at a zoom level."""
|
||||
|
||||
if zoom < 0:
|
||||
raise ProjectionError("zoom must be >= 0")
|
||||
if tile_size <= 0:
|
||||
raise ProjectionError("tile_size must be > 0")
|
||||
return tile_size * (2**zoom)
|
||||
|
||||
|
||||
def latlon_to_world(lat: float, lon: float, zoom: int, tile_size: int = DEFAULT_TILE_SIZE) -> Point:
|
||||
"""Project latitude/longitude to world pixel coordinates."""
|
||||
|
||||
size = map_size(zoom, tile_size)
|
||||
lat = clamp_latitude(lat)
|
||||
lon = ((lon + 180.0) % 360.0) - 180.0
|
||||
|
||||
sin_lat = math.sin(math.radians(lat))
|
||||
x = (lon + 180.0) / 360.0 * size
|
||||
y = (0.5 - math.log((1.0 + sin_lat) / (1.0 - sin_lat)) / (4.0 * math.pi)) * size
|
||||
return (x, y)
|
||||
|
||||
|
||||
def world_to_latlon(x: float, y: float, zoom: int, tile_size: int = DEFAULT_TILE_SIZE) -> LatLon:
|
||||
"""Unproject world pixel coordinates to latitude/longitude."""
|
||||
|
||||
size = map_size(zoom, tile_size)
|
||||
lon = x / size * 360.0 - 180.0
|
||||
n = math.pi - 2.0 * math.pi * y / size
|
||||
lat = math.degrees(math.atan(math.sinh(n)))
|
||||
return (lat, lon)
|
||||
|
||||
|
||||
def latlon_to_tile(lat: float, lon: float, zoom: int) -> tuple[int, int, int]:
|
||||
"""Return the XYZ tile coordinate containing a latitude/longitude point."""
|
||||
|
||||
x, y = latlon_to_world(lat, lon, zoom)
|
||||
scale = 2**zoom
|
||||
tile_x = min(max(int(x // DEFAULT_TILE_SIZE), 0), scale - 1)
|
||||
tile_y = min(max(int(y // DEFAULT_TILE_SIZE), 0), scale - 1)
|
||||
return (tile_x, tile_y, zoom)
|
||||
|
||||
|
||||
def world_to_screen(
|
||||
world_x: float,
|
||||
world_y: float,
|
||||
*,
|
||||
center: LatLon,
|
||||
zoom: int,
|
||||
width: int,
|
||||
height: int,
|
||||
tile_size: int = DEFAULT_TILE_SIZE,
|
||||
) -> Point:
|
||||
"""Convert world pixels to screen pixels for a centered viewport."""
|
||||
|
||||
center_x, center_y = latlon_to_world(center[0], center[1], zoom, tile_size)
|
||||
return (world_x - center_x + width / 2.0, world_y - center_y + height / 2.0)
|
||||
|
||||
|
||||
def screen_to_world(
|
||||
screen_x: float,
|
||||
screen_y: float,
|
||||
*,
|
||||
center: LatLon,
|
||||
zoom: int,
|
||||
width: int,
|
||||
height: int,
|
||||
tile_size: int = DEFAULT_TILE_SIZE,
|
||||
) -> Point:
|
||||
"""Convert screen pixels to world pixels for a centered viewport."""
|
||||
|
||||
center_x, center_y = latlon_to_world(center[0], center[1], zoom, tile_size)
|
||||
return (screen_x + center_x - width / 2.0, screen_y + center_y - height / 2.0)
|
||||
|
||||
@@ -1 +1,145 @@
|
||||
"""Tile provider definitions and registry."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from string import Formatter
|
||||
from threading import RLock
|
||||
|
||||
from .exceptions import InvalidProviderError, ProviderExistsError, ProviderNotFoundError
|
||||
|
||||
_REQUIRED_TEMPLATE_FIELDS = frozenset({"x", "y", "z"})
|
||||
_OPTIONAL_TEMPLATE_FIELDS = frozenset({"s", "r", "ext"})
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class TileProvider:
|
||||
"""XYZ raster tile provider definition."""
|
||||
|
||||
name: str
|
||||
url_template: str
|
||||
min_zoom: int = 0
|
||||
max_zoom: int = 19
|
||||
tile_size: int = 256
|
||||
attribution: str = ""
|
||||
headers: dict[str, str] = field(default_factory=dict)
|
||||
subdomains: tuple[str, ...] = ()
|
||||
retina: bool = False
|
||||
file_extension: str | None = None
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
name = self.name.strip()
|
||||
if not name:
|
||||
raise InvalidProviderError("provider name must not be empty")
|
||||
if name != self.name:
|
||||
object.__setattr__(self, "name", name)
|
||||
|
||||
if not self.url_template.strip():
|
||||
raise InvalidProviderError("provider url_template must not be empty")
|
||||
|
||||
fields = {
|
||||
field_name
|
||||
for _, field_name, _, _ in Formatter().parse(self.url_template)
|
||||
if field_name is not None and field_name != ""
|
||||
}
|
||||
missing = _REQUIRED_TEMPLATE_FIELDS - fields
|
||||
if missing:
|
||||
missing_text = ", ".join(sorted(missing))
|
||||
raise InvalidProviderError(f"provider url_template missing field(s): {missing_text}")
|
||||
|
||||
unknown = fields - _REQUIRED_TEMPLATE_FIELDS - _OPTIONAL_TEMPLATE_FIELDS
|
||||
if unknown:
|
||||
unknown_text = ", ".join(sorted(unknown))
|
||||
raise InvalidProviderError(
|
||||
f"provider url_template contains unknown field(s): {unknown_text}"
|
||||
)
|
||||
|
||||
if self.min_zoom < 0:
|
||||
raise InvalidProviderError("provider min_zoom must be >= 0")
|
||||
if self.max_zoom < self.min_zoom:
|
||||
raise InvalidProviderError("provider max_zoom must be >= min_zoom")
|
||||
if self.tile_size <= 0:
|
||||
raise InvalidProviderError("provider tile_size must be > 0")
|
||||
|
||||
object.__setattr__(self, "headers", dict(self.headers))
|
||||
object.__setattr__(self, "subdomains", tuple(self.subdomains))
|
||||
|
||||
def build_url(self, *, x: int, y: int, z: int) -> str:
|
||||
"""Build a concrete tile URL for an XYZ tile coordinate."""
|
||||
|
||||
if z < self.min_zoom or z > self.max_zoom:
|
||||
raise InvalidProviderError(
|
||||
f"zoom {z} is outside provider range {self.min_zoom}-{self.max_zoom}"
|
||||
)
|
||||
|
||||
subdomain = ""
|
||||
if self.subdomains:
|
||||
subdomain = self.subdomains[(x + y + z) % len(self.subdomains)]
|
||||
|
||||
retina_suffix = "@2x" if self.retina else ""
|
||||
extension = self.file_extension or ""
|
||||
return self.url_template.format(
|
||||
x=x,
|
||||
y=y,
|
||||
z=z,
|
||||
s=subdomain,
|
||||
r=retina_suffix,
|
||||
ext=extension,
|
||||
)
|
||||
|
||||
|
||||
OSM = TileProvider(
|
||||
name="osm",
|
||||
url_template="https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
min_zoom=0,
|
||||
max_zoom=19,
|
||||
tile_size=256,
|
||||
attribution="\u00a9 OpenStreetMap contributors",
|
||||
)
|
||||
|
||||
_providers: dict[str, TileProvider] = {OSM.name: OSM}
|
||||
_providers_lock = RLock()
|
||||
|
||||
|
||||
def register_provider(provider: TileProvider, *, replace: bool = False) -> None:
|
||||
"""Register a tile provider by name."""
|
||||
|
||||
if not isinstance(provider, TileProvider):
|
||||
raise InvalidProviderError("provider must be a TileProvider")
|
||||
|
||||
with _providers_lock:
|
||||
if provider.name in _providers and not replace:
|
||||
raise ProviderExistsError(f"provider already registered: {provider.name}")
|
||||
_providers[provider.name] = provider
|
||||
|
||||
|
||||
def unregister_provider(name: str) -> None:
|
||||
"""Remove a registered tile provider."""
|
||||
|
||||
with _providers_lock:
|
||||
if name not in _providers:
|
||||
raise ProviderNotFoundError(f"provider not registered: {name}")
|
||||
del _providers[name]
|
||||
|
||||
|
||||
def get_provider(name: str) -> TileProvider:
|
||||
"""Return a registered tile provider."""
|
||||
|
||||
with _providers_lock:
|
||||
try:
|
||||
return _providers[name]
|
||||
except KeyError as exc:
|
||||
raise ProviderNotFoundError(f"provider not registered: {name}") from exc
|
||||
|
||||
|
||||
def get_default_provider() -> TileProvider:
|
||||
"""Return the default OpenStreetMap provider."""
|
||||
|
||||
return get_provider(OSM.name)
|
||||
|
||||
|
||||
def list_providers() -> list[str]:
|
||||
"""List registered provider names in stable sorted order."""
|
||||
|
||||
with _providers_lock:
|
||||
return sorted(_providers)
|
||||
|
||||
@@ -1 +1,31 @@
|
||||
"""Shared type aliases and small value objects."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import TypeAlias
|
||||
|
||||
Tag: TypeAlias = str | int
|
||||
LatLon: TypeAlias = tuple[float, float]
|
||||
Point: TypeAlias = tuple[float, float]
|
||||
Bounds: TypeAlias = tuple[LatLon, LatLon]
|
||||
TileCoord: TypeAlias = tuple[int, int, int]
|
||||
Color: TypeAlias = tuple[int, int, int] | tuple[int, int, int, int]
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class ScreenPoint:
|
||||
"""A pixel position in map widget coordinates."""
|
||||
|
||||
x: float
|
||||
y: float
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class GeoBounds:
|
||||
"""Latitude/longitude bounds with south-west and north-east corners."""
|
||||
|
||||
south: float
|
||||
west: float
|
||||
north: float
|
||||
east: float
|
||||
|
||||
@@ -1 +1,31 @@
|
||||
"""Dear PyGui map widget construction."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterator
|
||||
from contextlib import contextmanager
|
||||
|
||||
from .exceptions import DpgMapNotImplementedError
|
||||
from .providers import TileProvider
|
||||
from .types import LatLon, Tag
|
||||
|
||||
|
||||
@contextmanager
|
||||
def map_widget(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
center: LatLon = (0.0, 0.0),
|
||||
zoom: int = 2,
|
||||
provider: str | TileProvider | None = None,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
**kwargs: object,
|
||||
) -> Iterator[Tag | None]:
|
||||
"""Stub context manager for the future Dear PyGui widget."""
|
||||
|
||||
raise DpgMapNotImplementedError(
|
||||
"dpg_map.map_widget is not implemented until the GUI rebuild steps"
|
||||
)
|
||||
yield tag
|
||||
|
||||
Reference in New Issue
Block a user