Source code for dearpygui_obj.drawing

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, NamedTuple

from dearpygui import dearpygui as dpgcore
from dearpygui_obj import _register_item_type
from dearpygui_obj.data import export_color_to_dpg, import_color_from_dpg
from dearpygui_obj.wrapper.widget import Widget, ItemWidgetMx
from dearpygui_obj.wrapper.drawing import DrawCommand, DrawProperty

if TYPE_CHECKING:
    from typing import Any, Optional, Tuple, Sequence
    from dearpygui_obj.data import ColorRGBA
    from dearpygui_obj.window import Window
    from dearpygui_obj.wrapper.drawing import DrawConfigData


[docs]class DrawingCanvas(ABC): """Abstract base class for drawing.""" @property @abstractmethod def id(self) -> str: ...
[docs] def clear(self) -> None: """Clears the drawing. Warning: Any :class:`.DrawCommand` objects created using this canvas must not be used after this method is called. This includes reading or writing to any properties of :class:`DrawCommand` objects. """ dpgcore.clear_drawing(self.id)
[docs] def draw_line(self, p1: Tuple[float, float], p2: Tuple[float, float], color: ColorRGBA, thickness: int) -> DrawLine: """See :class:`.DrawLine`""" return DrawLine(self, p1, p2, color, thickness)
[docs] def draw_rectangle(self, pmin: Tuple[float, float], pmax: Tuple[float, float], color: ColorRGBA, **kwargs: Any) -> DrawRectangle: """See :class:`.DrawRectangle` for keyword arguments.""" return DrawRectangle(self, pmin, pmax, color, **kwargs)
[docs] def draw_circle(self, center: Tuple[float, float], radius: float, color: ColorRGBA, **kwargs: Any) -> DrawCircle: """See :class:`.DrawCircle` for keyword arguments.""" return DrawCircle(self, center, radius, color, **kwargs)
[docs] def draw_text(self, pos: Tuple[float, float], text: str, **kwargs) -> DrawText: """See :class:`.DrawText` for keyword arguments.""" return DrawText(self, pos, text, **kwargs)
[docs] def draw_arrow(self, p1: Tuple[float, float], p2: Tuple[float, float], color: ColorRGBA, thickness: int, arrow_size: int) -> DrawArrow: """See :class:`.DrawArrow` for keyword arguments.""" return DrawArrow(self, p1, p2, color, thickness, arrow_size)
[docs] def draw_polyline(self, points: Sequence[Tuple[float, float]], color: ColorRGBA, **kwargs: Any) -> DrawPolyLine: """See :class:`.DrawPolyLine` for keyword arguments.""" return DrawPolyLine(self, points, color, **kwargs)
[docs] def draw_triangle(self, p1: Tuple[float, float], p2: Tuple[float, float], p3: Tuple[float, float], color: ColorRGBA, **kwargs: Any) -> DrawTriangle: """See :class:`.DrawTriangle` for keyword arguments.""" return DrawTriangle(self, p1, p2, p3, color, **kwargs)
[docs] def draw_quad(self, p1: Tuple[float, float], p2: Tuple[float, float], p3: Tuple[float, float], p4: Tuple[float, float], color: ColorRGBA, **kwargs: Any) -> DrawQuad: """See :class:`.DrawQuod` for keyword arguments.""" return DrawQuad(self, p1, p2, p3, p4, color, **kwargs)
[docs] def draw_polygon(self, points: Sequence[Tuple[float, float]], color: ColorRGBA, **kwargs) -> DrawPolygon: """See :class:`.DrawPolygon` for keyword arguments.""" return DrawPolygon(self, points, color, **kwargs)
[docs] def draw_bezier_curve(self, p1: Tuple[float, float], p2: Tuple[float, float], p3: Tuple[float, float], p4: Tuple[float, float], color: ColorRGBA, **kwargs: Any) -> DrawBezierCurve: """See :class:`.DrawBezierCurve` for keyword arguments.""" return DrawBezierCurve(self, p1, p2, p3, p4, color, **kwargs)
[docs]@_register_item_type('mvAppItemType::Drawing') class Drawing(Widget, ItemWidgetMx, DrawingCanvas): """A widget that displays the result of drawing commands.""" def __init__(self, size: Tuple[int, int] = (300, 300), **config): super().__init__(size=size, **config) def __setup_add_widget__(self, dpg_args) -> None: dpgcore.add_drawing(self.id, **dpg_args)
[docs] def get_mouse_pos(self) -> Optional[Tuple[int, int]]: """Get the mouse position within the drawing, or ``None`` if the drawing is not hovered.""" if not self.is_hovered(): return None return dpgcore.get_drawing_mouse_pos()
[docs]class WindowCanvas(DrawingCanvas): """A :class:`.DrawingCanvas` that can be used to draw onto a window. Can also be obtained from :meth:`.Window.get_canvas`. To draw on the foreground or background of the main viewport, see :attr:`.MainWindow.foreground` and :attr:`.MainWindow.background`.""" def __init__(self, window: Window): self._id = window.id @property def id(self) -> str: return self._id
## Draw Commands
[docs]class Pos2D(NamedTuple): """2D position data used for drawing.""" x: float #: x coordinate y: float #: y coordinate
class DrawPropertyColorRGBA(DrawProperty): def fvalue(self, instance: Widget) -> Any: return import_color_from_dpg(instance.get_config()[self.key]) def fconfig(self, instance: Widget, value: ColorRGBA) -> DrawConfigData: return {self.key : export_color_to_dpg(value)} class DrawPropertyPos2D(DrawProperty): def fvalue(self, instance: DrawCommand) -> Pos2D: return Pos2D(*instance.get_config()[self.key]) def fconfig(self, instance: DrawCommand, value: Tuple[float, float]) -> DrawConfigData: return {self.key : list(value)}
[docs]class DrawLine(DrawCommand): """Draws a line.""" p1: Tuple[float, float] = DrawPropertyPos2D() p2: Tuple[float, float] = DrawPropertyPos2D() color: ColorRGBA = DrawPropertyColorRGBA() thickness: int = DrawProperty() def __draw_internal__(self, draw_args) -> None: dpgcore.draw_line(self.canvas.id, tag=self.id, **draw_args)
[docs]class DrawRectangle(DrawCommand): """Draws a rectangle.""" pmin: Tuple[float, float] = DrawPropertyPos2D() pmax: Tuple[float, float] = DrawPropertyPos2D() color: ColorRGBA = DrawPropertyColorRGBA() fill: ColorRGBA = DrawPropertyColorRGBA() rounding: float = DrawProperty() thickness: float = DrawProperty() def __draw_internal__(self, draw_args) -> None: dpgcore.draw_rectangle(self.canvas.id, tag=self.id, **draw_args)
[docs]class DrawCircle(DrawCommand): """Draws a circle.""" center: Tuple[float, float] = DrawPropertyPos2D() radius: float = DrawProperty() color: ColorRGBA = DrawPropertyColorRGBA() segments: int = DrawProperty() thickness: float = DrawProperty() fill: ColorRGBA = DrawPropertyColorRGBA() def __draw_internal__(self, draw_args) -> None: dpgcore.draw_circle(self.canvas.id, tag=self.id, **draw_args)
[docs]class DrawText(DrawCommand): """Draws text.""" pos: Tuple[float, float] = DrawPropertyPos2D() text: str = DrawProperty() color: ColorRGBA = DrawPropertyColorRGBA() font_size: int = DrawProperty(key='size') def __draw_internal__(self, draw_args) -> None: dpgcore.draw_text(self.canvas.id, tag=self.id, **draw_args)
[docs]class DrawArrow(DrawCommand): """Draw a line with an arrowhead.""" p1: Tuple[float, float] = DrawPropertyPos2D() p2: Tuple[float, float] = DrawPropertyPos2D() color: ColorRGBA = DrawPropertyColorRGBA() thickness: int = DrawProperty() arrow_size: int = DrawProperty(key='size') def __draw_internal__(self, draw_args) -> None: dpgcore.draw_arrow(self.canvas.id, tag=self.id, **draw_args)
[docs]class DrawPolyLine(DrawCommand): """Draws connected lines.""" @DrawProperty() def points(self) -> Sequence[Tuple[float, float]]: return [Pos2D(*p) for p in self.get_config()['points']] @points.getconfig def points(self, value: Sequence[Tuple[float, float]]): return { 'points' : [ list(p) for p in value ] } color: ColorRGBA = DrawPropertyColorRGBA() closed: bool = DrawProperty() thickness: float = DrawProperty() def __draw_internal__(self, draw_args) -> None: dpgcore.draw_polyline(self.canvas.id, tag=self.id, **draw_args)
[docs]class DrawTriangle(DrawCommand): """Draws a triangle.""" p1: Tuple[float, float] = DrawPropertyPos2D() p2: Tuple[float, float] = DrawPropertyPos2D() p3: Tuple[float, float] = DrawPropertyPos2D() color: ColorRGBA = DrawPropertyColorRGBA() fill: ColorRGBA = DrawPropertyColorRGBA() thickness: float = DrawProperty() def __draw_internal__(self, draw_args) -> None: dpgcore.draw_triangle(self.canvas.id, tag=self.id, **draw_args)
[docs]class DrawQuad(DrawCommand): """Draws a quadrilateral.""" p1: Tuple[float, float] = DrawPropertyPos2D() p2: Tuple[float, float] = DrawPropertyPos2D() p3: Tuple[float, float] = DrawPropertyPos2D() p4: Tuple[float, float] = DrawPropertyPos2D() color: ColorRGBA = DrawPropertyColorRGBA() fill: ColorRGBA = DrawPropertyColorRGBA() thickness: float = DrawProperty() def __draw_internal__(self, draw_args) -> None: dpgcore.draw_quad(self.canvas.id, tag=self.id, **draw_args)
[docs]class DrawPolygon(DrawCommand): """Draws a polygon.""" @DrawProperty() def points(self) -> Sequence[Tuple[float, float]]: return [Pos2D(*p) for p in self.get_config()['points']] @points.getconfig def points(self, value: Sequence[Tuple[float, float]]): return { 'points' : [ list(p) for p in value ] } color: ColorRGBA = DrawPropertyColorRGBA() fill: ColorRGBA = DrawPropertyColorRGBA() thickness: float = DrawProperty() def __draw_internal__(self, draw_args) -> None: dpgcore.draw_polygon(self.canvas.id, tag=self.id, **draw_args)
[docs]class DrawBezierCurve(DrawCommand): """Draws a bezier curve.""" p1: Tuple[float, float] = DrawPropertyPos2D() p2: Tuple[float, float] = DrawPropertyPos2D() p3: Tuple[float, float] = DrawPropertyPos2D() p4: Tuple[float, float] = DrawPropertyPos2D() color: ColorRGBA = DrawPropertyColorRGBA() thickness: float = DrawProperty() segments: int = DrawProperty() def __draw_internal__(self, draw_args) -> None: dpgcore.draw_bezier_curve(self.canvas.id, tag=self.id, **draw_args)
## class DrawImage TODO __all__ = [ 'Drawing', 'WindowCanvas', 'DrawLine', 'DrawRectangle', 'DrawCircle', 'DrawText', 'DrawArrow', 'DrawPolyLine', 'DrawTriangle', 'DrawQuad', 'DrawPolygon', 'DrawBezierCurve', ] if TYPE_CHECKING: from dearpygui_obj.wrapper.drawing import DrawCommand __all__.extend([ 'DrawingCanvas', 'DrawCommand', ])