123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- from __future__ import annotations
- import traceback
- from typing import Any, Callable, Dict, List, Optional
- from justpy import WebPage
- from ..events import MouseEventArguments, handle_event
- from .custom_view import CustomView
- from .element import Element
- CustomView.use(__file__)
- class InteractiveImageView(CustomView):
- def __init__(self, source: str, on_mouse: Callable, events: List[str], cross: bool):
- super().__init__('interactive_image', source=source, events=events, cross=cross, svg_content='')
- self.allowed_events = ['onMouse', 'onConnect']
- self.initialize(onMouse=on_mouse, onConnect=self.on_connect)
- self.sockets = []
- def on_connect(self, msg):
- self.prune_sockets()
- self.sockets.append(msg.websocket)
- def prune_sockets(self):
- page_sockets = [s for page_id in self.pages for s in WebPage.sockets.get(page_id, {}).values()]
- self.sockets = [s for s in self.sockets if s in page_sockets]
- class InteractiveImage(Element):
- def __init__(self, source: str, *,
- on_mouse: Optional[Callable] = None, events: List[str] = ['click'], cross: bool = False):
- """Interactive Image
- Create an image with an SVG overlay that handles mouse events and yields image coordinates.
- :param source: the source of the image; can be an URL or a base64 string
- :param on_mouse: callback for mouse events (yields `type`, `image_x` and `image_y`)
- :param events: list of JavaScript events to subscribe to (default: `['click']`)
- :param cross: whether to show crosshairs (default: `False`)
- """
- self.mouse_handler = on_mouse
- super().__init__(InteractiveImageView(source, self.handle_mouse, events, cross))
- def handle_mouse(self, msg: Dict[str, Any]):
- if self.mouse_handler is None:
- return
- try:
- arguments = MouseEventArguments(
- sender=self,
- socket=msg.get('websocket'),
- type=msg.get('mouse_event_type'),
- image_x=msg.get('image_x'),
- image_y=msg.get('image_y'),
- )
- handle_event(self.mouse_handler, arguments)
- except:
- traceback.print_exc()
- async def set_source(self, source: str):
- self.view.options.source = source
- self.view.prune_sockets()
- for socket in self.view.sockets:
- await self.view.run_method(f'set_source("{source}")', socket)
- @property
- def svg_content(self) -> str:
- return self.view.options.svg_content
- @svg_content.setter
- def svg_content(self, content: str):
- self.view.options.svg_content = content
|