Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
flet / core / map / map.py
Size: Mime:
import json
from dataclasses import dataclass
from enum import Enum, EnumMeta, IntFlag
from typing import Any, List, Optional, Tuple, Union
from warnings import warn

from flet.core.animation import AnimationCurve, AnimationValue
from flet.core.badge import BadgeValue
from flet.core.constrained_control import ConstrainedControl
from flet.core.control import OptionalNumber
from flet.core.event_handler import EventHandler
from flet.core.map.map_layer import MapLayer
from flet.core.ref import Ref
from flet.core.tooltip import TooltipValue
from flet.core.transform import Offset
from flet.core.types import (
    ColorEnums,
    ColorValue,
    ControlEvent,
    DurationValue,
    Number,
    OffsetValue,
    OptionalControlEventCallable,
    OptionalEventCallable,
    ResponsiveNumber,
    RotateValue,
    ScaleValue,
)
from flet.utils import deprecated


@dataclass
class MapLatitudeLongitude:
    latitude: Union[float, int]
    longitude: Union[float, int]


@dataclass
class MapLatitudeLongitudeBounds:
    corner_1: MapLatitudeLongitude
    corner_2: MapLatitudeLongitude


class MapInteractiveFlag(IntFlag):
    NONE = 0
    DRAG = 1 << 0
    FLING_ANIMATION = 1 << 1
    PINCH_MOVE = 1 << 2
    PINCH_ZOOM = 1 << 3
    DOUBLE_TAP_ZOOM = 1 << 4
    DOUBLE_TAP_DRAG_ZOOM = 1 << 5
    SCROLL_WHEEL_ZOOM = 1 << 6
    ROTATE = 1 << 7
    ALL = (
        (1 << 0)
        | (1 << 1)
        | (1 << 2)
        | (1 << 3)
        | (1 << 4)
        | (1 << 5)
        | (1 << 6)
        | (1 << 7)
    )


class MapMultiFingerGesture(IntFlag):
    NONE = 0
    PINCH_MOVE = 1 << 0
    PINCH_ZOOM = 1 << 1
    ROTATE = 1 << 2
    ALL = (1 << 0) | (1 << 1) | (1 << 2)


class MapPointerDeviceTypeDeprecated(EnumMeta):
    def __getattribute__(self, item):
        if item in [
            "TOUCH",
            "MOUSE",
            "STYLUS",
            "INVERTED_STYLUS",
            "TRACKPAD",
            "UNKNOWN",
        ]:
            warn(
                "MapPointerDeviceType enum is deprecated since version 0.25.0 "
                "and will be removed in version 0.28.0. Use PointerDeviceType enum instead.",
                DeprecationWarning,
                stacklevel=2,
            )
        return EnumMeta.__getattribute__(self, item)


class MapPointerDeviceType(Enum, metaclass=MapPointerDeviceTypeDeprecated):
    TOUCH = "touch"
    MOUSE = "mouse"
    STYLUS = "stylus"
    INVERTED_STYLUS = "invertedStylus"
    TRACKPAD = "trackpad"
    UNKNOWN = "unknown"


@dataclass
class MapInteractionConfiguration:
    enable_multi_finger_gesture_race: Optional[bool] = None
    pinch_move_threshold: OptionalNumber = None
    scroll_wheel_velocity: OptionalNumber = None
    pinch_zoom_threshold: OptionalNumber = None
    rotation_threshold: OptionalNumber = None
    flags: Optional[MapInteractiveFlag] = None
    rotation_win_gestures: Optional[MapMultiFingerGesture] = None
    pinch_move_win_gestures: Optional[MapMultiFingerGesture] = None
    pinch_zoom_win_gestures: Optional[MapMultiFingerGesture] = None


@deprecated(
    reason="Map control has been moved to a separate Python package: https://pypi.org/project/flet-map. "
    + "Read more about this change in Flet blog: https://flet.dev/blog/flet-v-0-26-release-announcement",
    version="0.26.0",
    delete_version="0.29.0",
)
class Map(ConstrainedControl):
    """
    Map Control.

    -----

    Online docs: https://flet.dev/docs/controls/map
    """

    def __init__(
        self,
        layers: List[MapLayer],
        initial_center: Optional[MapLatitudeLongitude] = None,
        initial_rotation: OptionalNumber = None,
        initial_zoom: OptionalNumber = None,
        interaction_configuration: Optional[MapInteractionConfiguration] = None,
        bgcolor: Optional[ColorValue] = None,
        keep_alive: Optional[bool] = None,
        max_zoom: OptionalNumber = None,
        min_zoom: OptionalNumber = None,
        animation_curve: Optional[AnimationCurve] = None,
        animation_duration: Optional[DurationValue] = None,
        on_init: OptionalControlEventCallable = None,
        on_tap: OptionalEventCallable["MapTapEvent"] = None,
        on_hover: OptionalEventCallable["MapHoverEvent"] = None,
        on_secondary_tap: OptionalEventCallable["MapTapEvent"] = None,
        on_long_press: OptionalEventCallable["MapTapEvent"] = None,
        on_event: OptionalEventCallable["MapEvent"] = None,
        on_position_change: OptionalEventCallable["MapPositionChangeEvent"] = None,
        on_pointer_down: OptionalEventCallable["MapPointerEvent"] = None,
        on_pointer_cancel: OptionalEventCallable["MapPointerEvent"] = None,
        on_pointer_up: OptionalEventCallable["MapPointerEvent"] = None,
        #
        # ConstrainedControl
        #
        ref: Optional[Ref] = None,
        key: Optional[str] = None,
        width: OptionalNumber = None,
        height: OptionalNumber = None,
        left: OptionalNumber = None,
        top: OptionalNumber = None,
        right: OptionalNumber = None,
        bottom: OptionalNumber = None,
        expand: Union[None, bool, int] = None,
        expand_loose: Optional[bool] = None,
        col: Optional[ResponsiveNumber] = None,
        opacity: OptionalNumber = None,
        rotate: Optional[RotateValue] = None,
        scale: Optional[ScaleValue] = None,
        offset: Optional[OffsetValue] = None,
        aspect_ratio: OptionalNumber = None,
        animate_opacity: Optional[AnimationValue] = None,
        animate_size: Optional[AnimationValue] = None,
        animate_position: Optional[AnimationValue] = None,
        animate_rotation: Optional[AnimationValue] = None,
        animate_scale: Optional[AnimationValue] = None,
        animate_offset: Optional[AnimationValue] = None,
        on_animation_end: OptionalControlEventCallable = None,
        tooltip: Optional[TooltipValue] = None,
        badge: Optional[BadgeValue] = None,
        visible: Optional[bool] = None,
        disabled: Optional[bool] = None,
        data: Any = None,
    ):
        ConstrainedControl.__init__(
            self,
            ref=ref,
            key=key,
            width=width,
            height=height,
            left=left,
            top=top,
            right=right,
            bottom=bottom,
            expand=expand,
            expand_loose=expand_loose,
            col=col,
            opacity=opacity,
            rotate=rotate,
            scale=scale,
            offset=offset,
            aspect_ratio=aspect_ratio,
            animate_opacity=animate_opacity,
            animate_size=animate_size,
            animate_position=animate_position,
            animate_rotation=animate_rotation,
            animate_scale=animate_scale,
            animate_offset=animate_offset,
            on_animation_end=on_animation_end,
            tooltip=tooltip,
            badge=badge,
            visible=visible,
            disabled=disabled,
            data=data,
        )
        self.__on_tap = EventHandler(lambda e: MapTapEvent(e))
        self._add_event_handler("tap", self.__on_tap.get_handler())

        self.__on_hover = EventHandler(lambda e: MapHoverEvent(e))
        self._add_event_handler("hover", self.__on_hover.get_handler())

        self.__on_secondary_tap = EventHandler(lambda e: MapTapEvent(e))
        self._add_event_handler("secondary_tap", self.__on_secondary_tap.get_handler())

        self.__on_long_press = EventHandler(lambda e: MapTapEvent(e))
        self._add_event_handler("long_press", self.__on_long_press.get_handler())

        self.__on_event = EventHandler(lambda e: MapEvent(e))
        self._add_event_handler("event", self.__on_event.get_handler())

        self.__on_position_change = EventHandler(lambda e: MapPositionChangeEvent(e))
        self._add_event_handler(
            "position_change", self.__on_position_change.get_handler()
        )

        self.__on_pointer_down = EventHandler(lambda e: MapPointerEvent(e))
        self._add_event_handler("pointer_down", self.__on_pointer_down.get_handler())

        self.__on_pointer_cancel = EventHandler(lambda e: MapPointerEvent(e))
        self._add_event_handler(
            "pointer_cancel", self.__on_pointer_cancel.get_handler()
        )

        self.__on_pointer_up = EventHandler(lambda e: MapPointerEvent(e))
        self._add_event_handler("pointer_up", self.__on_pointer_up.get_handler())

        self.layers = layers
        self.initial_center = initial_center
        self.initial_rotation = initial_rotation
        self.initial_zoom = initial_zoom
        self.interaction_configuration = interaction_configuration
        self.bgcolor = bgcolor
        self.keep_alive = keep_alive
        self.max_zoom = max_zoom
        self.min_zoom = min_zoom
        self.animation_curve = animation_curve
        self.animation_duration = animation_duration
        self.on_tap = on_tap
        self.on_hover = on_hover
        self.on_secondary_tap = on_secondary_tap
        self.on_init = on_init
        self.on_long_press = on_long_press
        self.on_event = on_event
        self.on_position_change = on_position_change
        self.on_pointer_down = on_pointer_down
        self.on_pointer_cancel = on_pointer_cancel
        self.on_pointer_up = on_pointer_up

    def before_update(self):
        self._set_attr_json("initialCenter", self.__initial_center)
        self._set_attr_json("animationDuration", self.__animation_duration)
        self._set_attr_json(
            "interactionConfiguration", self.__interaction_configuration
        )

    def rotate_from(
        self,
        degree: Number,
        animation_curve: Optional[AnimationCurve] = None,
    ):
        self.invoke_method(
            "rotate_from",
            arguments={
                "degree": degree,
                "curve": animation_curve.value if animation_curve else None,
            },
        )

    def reset_rotation(
        self,
        animation_curve: Optional[AnimationCurve] = None,
        animation_duration: Optional[DurationValue] = None,
    ):
        self.invoke_method(
            "reset_rotation",
            arguments={
                "curve": animation_curve.value if animation_curve else None,
                "duration": self._convert_attr_json(animation_duration),
            },
        )

    def zoom_in(
        self,
        animation_curve: Optional[AnimationCurve] = None,
        animation_duration: Optional[DurationValue] = None,
    ):
        self.invoke_method(
            "zoom_in",
            arguments={
                "curve": animation_curve.value if animation_curve else None,
                "duration": self._convert_attr_json(animation_duration),
            },
        )

    def zoom_out(
        self,
        animation_curve: Optional[AnimationCurve] = None,
        animation_duration: Optional[DurationValue] = None,
    ):
        self.invoke_method(
            "zoom_out",
            arguments={
                "curve": animation_curve.value if animation_curve else None,
                "duration": self._convert_attr_json(animation_duration),
            },
        )

    def zoom_to(
        self,
        zoom: Number,
        animation_curve: Optional[AnimationCurve] = None,
        animation_duration: Optional[DurationValue] = None,
    ):
        self.invoke_method(
            "zoom_to",
            arguments={
                "zoom": zoom,
                "curve": animation_curve.value if animation_curve else None,
                "duration": self._convert_attr_json(animation_duration),
            },
        )

    def move_to(
        self,
        destination: Optional[MapLatitudeLongitude] = None,
        zoom: OptionalNumber = None,
        rotation: OptionalNumber = None,
        animation_curve: Optional[AnimationCurve] = None,
        animation_duration: Optional[DurationValue] = None,
        offset: Optional[Union[Offset, Tuple[Union[Number], Union[Number]]]] = None,
    ):
        if isinstance(offset, tuple):
            offset = Offset(offset[0], offset[1])
        self.invoke_method(
            "move_to",
            arguments={
                "lat": str(destination.latitude) if destination else None,
                "long": str(destination.longitude) if destination else None,
                "zoom": zoom,
                "ox": str(offset.x) if offset else None,
                "oy": str(offset.y) if offset else None,
                "rot": rotation,
                "curve": animation_curve.value if animation_curve else None,
                "duration": self._convert_attr_json(animation_duration),
            },
        )

    def center_on(
        self,
        point: Optional[MapLatitudeLongitude],
        zoom: OptionalNumber,
        animation_curve: Optional[AnimationCurve] = None,
        animation_duration: Optional[DurationValue] = None,
    ):
        self.invoke_method(
            "center_on",
            arguments={
                "lat": str(point.latitude) if point else None,
                "long": str(point.longitude) if point else None,
                "zoom": zoom,
                "curve": animation_curve.value if animation_curve else None,
                "duration": self._convert_attr_json(animation_duration),
            },
        )

    def _get_control_name(self):
        return "map"

    def _get_children(self):
        return self.__layers

    # layers
    @property
    def layers(self) -> List[MapLayer]:
        return self.__layers

    @layers.setter
    def layers(self, value: List[MapLayer]):
        self.__layers = value

    # initial_center
    @property
    def initial_center(self) -> Optional[MapLatitudeLongitude]:
        return self.__initial_center

    @initial_center.setter
    def initial_center(self, value: Optional[MapLatitudeLongitude]):
        self.__initial_center = value

    # initial_rotation
    @property
    def initial_rotation(self) -> OptionalNumber:
        return self._get_attr("initialRotation", data_type="float")

    @initial_rotation.setter
    def initial_rotation(self, value: OptionalNumber):
        self._set_attr("initialRotation", value)

    # initial_zoom
    @property
    def initial_zoom(self) -> OptionalNumber:
        return self._get_attr("initialZoom", data_type="float")

    @initial_zoom.setter
    def initial_zoom(self, value: OptionalNumber):
        self._set_attr("initialZoom", value)

    # interaction_configuration
    @property
    def interaction_configuration(self) -> Optional[MapInteractionConfiguration]:
        return self.__interaction_configuration

    @interaction_configuration.setter
    def interaction_configuration(self, value: Optional[MapInteractionConfiguration]):
        self.__interaction_configuration = value

    # bgcolor
    @property
    def bgcolor(self) -> Optional[ColorValue]:
        return self.__bgcolor

    @bgcolor.setter
    def bgcolor(self, value: Optional[ColorValue]):
        self.__bgcolor = value
        self._set_enum_attr("bgcolor", value, ColorEnums)

    # keep_alive
    @property
    def keep_alive(self) -> Optional[bool]:
        return self._get_attr("keepAlive", data_type="bool")

    @keep_alive.setter
    def keep_alive(self, value: Optional[bool]):
        self._set_attr("keepAlive", value)

    # max_zoom
    @property
    def max_zoom(self) -> OptionalNumber:
        return self._get_attr("maxZoom", data_type="float")

    @max_zoom.setter
    def max_zoom(self, value: OptionalNumber):
        self._set_attr("maxZoom", value)

    # min_zoom
    @property
    def min_zoom(self) -> OptionalNumber:
        return self._get_attr("minZoom", data_type="float")

    @min_zoom.setter
    def min_zoom(self, value: OptionalNumber):
        self._set_attr("minZoom", value)

    # animation_curve
    @property
    def animation_curve(self) -> Optional[AnimationCurve]:
        return self.__animation_curve

    @animation_curve.setter
    def animation_curve(self, value: Optional[AnimationCurve]):
        self.__animation_curve = value
        self._set_enum_attr("animationCurve", value, AnimationCurve)

    # animation_duration
    @property
    def animation_duration(self) -> Optional[DurationValue]:
        return self.__animation_duration

    @animation_duration.setter
    def animation_duration(self, value: Optional[DurationValue]):
        self.__animation_duration = value

    # on_tap
    @property
    def on_tap(self) -> OptionalEventCallable["MapTapEvent"]:
        return self.__on_tap.handler

    @on_tap.setter
    def on_tap(self, handler: OptionalEventCallable["MapTapEvent"]):
        self.__on_tap.handler = handler
        self._set_attr("onTap", True if handler is not None else None)

    # on_hover
    @property
    def on_hover(self) -> OptionalEventCallable["MapHoverEvent"]:
        return self.__on_hover.handler

    @on_hover.setter
    def on_hover(self, handler: OptionalEventCallable["MapHoverEvent"]):
        self.__on_hover.handler = handler
        self._set_attr("onHover", True if handler is not None else None)

    # on_secondary_tap
    @property
    def on_secondary_tap(self) -> OptionalEventCallable["MapTapEvent"]:
        return self.__on_secondary_tap.handler

    @on_secondary_tap.setter
    def on_secondary_tap(self, handler: OptionalEventCallable["MapTapEvent"]):
        self.__on_secondary_tap.handler = handler
        self._set_attr("onSecondaryTap", True if handler is not None else None)

    # on_long_press
    @property
    def on_long_press(self) -> OptionalEventCallable["MapTapEvent"]:
        return self.__on_long_press.handler

    @on_long_press.setter
    def on_long_press(self, handler: OptionalEventCallable["MapTapEvent"]):
        self.__on_long_press.handler = handler
        self._set_attr("onLongPress", True if handler is not None else None)

    # on_event
    @property
    def on_event(self) -> OptionalEventCallable["MapEvent"]:
        return self.__on_event.handler

    @on_event.setter
    def on_event(self, handler: OptionalEventCallable["MapEvent"]):
        self.__on_event.handler = handler
        self._set_attr("onEvent", True if handler is not None else None)

    # on_init
    @property
    def on_init(self) -> OptionalControlEventCallable:
        return self._get_event_handler("init")

    @on_init.setter
    def on_init(self, handler: OptionalControlEventCallable):
        self._add_event_handler("init", handler)
        self._set_attr("onInit", True if handler is not None else None)

    # on_position_change
    @property
    def on_position_change(self) -> OptionalEventCallable["MapPositionChangeEvent"]:
        return self.__on_position_change.handler

    @on_position_change.setter
    def on_position_change(
        self, handler: OptionalEventCallable["MapPositionChangeEvent"]
    ):
        self.__on_position_change.handler = handler
        self._set_attr("onPositionChange", True if handler is not None else None)

    # on_pointer_down
    @property
    def on_pointer_down(self) -> OptionalEventCallable["MapPointerEvent"]:
        return self.__on_pointer_down.handler

    @on_pointer_down.setter
    def on_pointer_down(self, handler: OptionalEventCallable["MapPointerEvent"]):
        self.__on_pointer_down.handler = handler
        self._set_attr("onPointerDown", True if handler is not None else None)

    # on_pointer_cancel
    @property
    def on_pointer_cancel(self) -> OptionalEventCallable["MapPointerEvent"]:
        return self.__on_pointer_cancel.handler

    @on_pointer_cancel.setter
    def on_pointer_cancel(self, handler: OptionalEventCallable["MapPointerEvent"]):
        self.__on_pointer_cancel.handler = handler
        self._set_attr("onPointerCancel", True if handler is not None else None)

    # on_pointer_up
    @property
    def on_pointer_up(self) -> OptionalEventCallable["MapPointerEvent"]:
        return self.__on_pointer_up.handler

    @on_pointer_up.setter
    def on_pointer_up(self, handler: OptionalEventCallable["MapPointerEvent"]):
        self.__on_pointer_up.handler = handler
        self._set_attr("onPointerUp", True if handler is not None else None)


class MapEventSource(Enum):
    MAP_CONTROLLER = "mapController"
    TAP = "tap"
    SECONDARY_TAP = "secondaryTap"
    LONG_PRESS = "longPress"
    DOUBLE_TAP = "doubleTap"
    DOUBLE_TAP_HOLD = "doubleTapHold"
    DRAG_START = "dragStart"
    ON_DRAG = "onDrag"
    DRAG_END = "dragEnd"
    MULTI_FINGER_GESTURE_START = "multiFingerGestureStart"
    ON_MULTI_FINGER = "onMultiFinger"
    MULTI_FINGER_GESTURE_END = "multiFingerEnd"
    FLING_ANIMATION_CONTROLLER = "flingAnimationController"
    DOUBLE_TAP_ZOOM_ANIMATION_CONTROLLER = "doubleTapZoomAnimationController"
    INTERACTIVE_FLAGS_CHANGED = "interactiveFlagsChanged"
    FIT_CAMERA = "fitCamera"
    CUSTOM = "custom"
    SCROLL_WHEEL = "scrollWheel"
    NON_ROTATED_SIZE_CHANGE = "nonRotatedSizeChange"
    CURSOR_KEYBOARD_ROTATION = "cursorKeyboardRotation"


class MapTapEvent(ControlEvent):
    def __init__(self, e: ControlEvent) -> None:
        super().__init__(e.target, e.name, e.data, e.control, e.page)
        d = json.loads(e.data)
        self.local_x: Optional[float] = d.get("lx")
        self.local_y: Optional[float] = d.get("ly")
        self.global_x: float = d.get("gx")
        self.global_y: float = d.get("gy")
        self.coordinates: MapLatitudeLongitude = MapLatitudeLongitude(
            d.get("lat"), d.get("long")
        )


class MapHoverEvent(ControlEvent):
    def __init__(self, e: ControlEvent) -> None:
        super().__init__(e.target, e.name, e.data, e.control, e.page)
        d = json.loads(e.data)
        self.local_x: Optional[float] = d.get("lx")
        self.local_y: Optional[float] = d.get("ly")
        self.global_x: float = d.get("gx")
        self.global_y: float = d.get("gy")
        self.device_type: MapPointerDeviceType = MapPointerDeviceType(d.get("kind"))
        self.coordinates: MapLatitudeLongitude = MapLatitudeLongitude(
            d.get("lat"), d.get("long")
        )


class MapPositionChangeEvent(ControlEvent):
    def __init__(self, e: ControlEvent) -> None:
        super().__init__(e.target, e.name, e.data, e.control, e.page)
        d = json.loads(e.data)
        self.min_zoom: Optional[float] = d.get("min_zoom")
        self.max_zoom: Optional[float] = d.get("max_zoom")
        self.rotation: float = d.get("rot")
        self.coordinates: MapLatitudeLongitude = MapLatitudeLongitude(
            d.get("lat"), d.get("long")
        )


class MapPointerEvent(ControlEvent):
    def __init__(self, e: ControlEvent) -> None:
        super().__init__(e.target, e.name, e.data, e.control, e.page)
        d = json.loads(e.data)
        self.device_type: MapPointerDeviceType = MapPointerDeviceType(d.get("kind"))
        self.global_y: float = d.get("gy")
        self.global_x: float = d.get("gx")
        self.coordinates: MapLatitudeLongitude = MapLatitudeLongitude(
            d.get("lat"), d.get("long")
        )


class MapEvent(ControlEvent):
    def __init__(self, e: ControlEvent) -> None:
        super().__init__(e.target, e.name, e.data, e.control, e.page)
        d = json.loads(e.data)
        self.source: MapEventSource = MapEventSource(d.get("src"))
        self.center: MapLatitudeLongitude = MapLatitudeLongitude(
            d.get("c_lat"), d.get("c_long")
        )
        self.zoom: float = d.get("zoom")
        self.min_zoom: float = d.get("min_zoom")
        self.max_zoom: float = d.get("max_zoom")
        self.rotation: float = d.get("rot")