drawlib 0.2.2__tar.gz → 0.2.3.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of drawlib might be problematic. Click here for more details.
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/PKG-INFO +1 -1
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/__init__.py +1 -1
- drawlib-0.2.3.dev1/drawlib/v0_2/private/smartarts/boxtree.py +114 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/smartarts/dsart.py +3 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/smartarts/gridlayout.py +275 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/smartarts/pyramid.py +189 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/smartarts/tree.py +274 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/activity.py +10 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/class_.py +10 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/communication.py +10 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/component.py +10 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/deployment.py +10 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/duml.py +12 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/object.py +10 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/package.py +10 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/sequence.py +10 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/state_machine.py +10 -0
- drawlib-0.2.3.dev1/drawlib/v0_2/private/umls/usecase.py +10 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/pyproject.toml +1 -1
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/LICENSE.txt +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/__main__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/apis.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/assets/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/assets/v0_2/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/assets/v0_2/fonticons/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/assets/v0_2/fonts/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/py.typed +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/__main__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/apis.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/command.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core/colors.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core/dimage.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core/fonts.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core/model.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core/model_system_default.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core/theme.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core/theme_officials.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core/theme_style_caches.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core/util.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core_canvas/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core_canvas/base.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core_canvas/canvas.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core_canvas/image.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core_canvas/line.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core_canvas/original_arrow.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core_canvas/original_polygon.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core_canvas/patches.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/core_canvas/text.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/download.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/dutil/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/dutil/dutil_canvas.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/dutil/dutil_color.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/dutil/dutil_script.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/dutil/settings.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/icons/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/icons/phosphor.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/icons/util.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/logging.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/smartarts/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/smartarts/bubblespeech.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/smartarts/sourcecode.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/util.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/__init__.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/args.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/color.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/coordinate.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/icon.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/image.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/line.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/shape.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/smartarts.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/style.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/text.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/drawlib/v0_2/private/validators/types.py +0 -0
- {drawlib-0.2.2 → drawlib-0.2.3.dev1}/pypi.md +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
"""BoxTree implementation module."""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import dataclasses
|
|
16
|
+
from typing import Callable, Dict, List, Literal, Optional, Tuple, Union
|
|
17
|
+
|
|
18
|
+
from drawlib.v0_2.private.core.model import LineStyle, ShapeStyle, ShapeTextStyle
|
|
19
|
+
from drawlib.v0_2.private.core.theme import dtheme
|
|
20
|
+
from drawlib.v0_2.private.core_canvas.canvas import line, rectangle
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BoxTreeNode:
|
|
24
|
+
"""Class for rendering smart art Tree."""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
text: str,
|
|
29
|
+
boxsize: Optional[Tuple[float, float]] = None,
|
|
30
|
+
boxstyle: Union[str, ShapeStyle, None] = None,
|
|
31
|
+
box_r: Optional[float] = None,
|
|
32
|
+
box_horizontal_margin: Optional[float] = None,
|
|
33
|
+
box_vertical_margin: Optional[float] = None,
|
|
34
|
+
textstyle: Union[str, ShapeTextStyle, None] = None,
|
|
35
|
+
linestyle: Union[str, LineStyle, None] = None,
|
|
36
|
+
line_horizontal_length: Optional[float] = None,
|
|
37
|
+
line_vertical_length: Optional[float] = None,
|
|
38
|
+
children: Optional[List[BoxTreeNode]] = None,
|
|
39
|
+
default_boxsize: Optional[Tuple[float, float]] = None,
|
|
40
|
+
default_boxstyle: Union[str, ShapeStyle, None] = None,
|
|
41
|
+
default_box_r: Optional[float] = None,
|
|
42
|
+
default_box_horizontal_margin: Optional[float] = None,
|
|
43
|
+
default_box_vertical_margin: Optional[float] = None,
|
|
44
|
+
default_textstyle: Union[str, ShapeTextStyle, None] = None,
|
|
45
|
+
default_linestyle: Union[str, LineStyle, None] = None,
|
|
46
|
+
default_line_horizontal_length: Optional[float] = None,
|
|
47
|
+
default_line_vertical_length: Optional[float] = None,
|
|
48
|
+
) -> None:
|
|
49
|
+
"""Initialize class."""
|
|
50
|
+
self._text = text
|
|
51
|
+
|
|
52
|
+
self._boxsize = boxsize
|
|
53
|
+
if isinstance(boxstyle, str):
|
|
54
|
+
boxstyle = dtheme.rectanglestyles.get(boxstyle)
|
|
55
|
+
self._boxstyle = boxstyle
|
|
56
|
+
self._box_r = box_r
|
|
57
|
+
self._box_horizontal_margin = box_horizontal_margin
|
|
58
|
+
self._box_vertical_margin = box_vertical_margin
|
|
59
|
+
|
|
60
|
+
if isinstance(textstyle, str):
|
|
61
|
+
textstyle = dtheme.rectangletextstyles.get(textstyle)
|
|
62
|
+
self._textstyle = textstyle
|
|
63
|
+
if isinstance(linestyle, str):
|
|
64
|
+
linestyle = dtheme.linestyles.get(linestyle)
|
|
65
|
+
self._linestyle = linestyle
|
|
66
|
+
|
|
67
|
+
self._line_horizontal_length = line_horizontal_length
|
|
68
|
+
self._line_vertical_length = line_vertical_length
|
|
69
|
+
|
|
70
|
+
if children is None:
|
|
71
|
+
self._children: List[BoxTreeNode] = []
|
|
72
|
+
else:
|
|
73
|
+
self._children: List[BoxTreeNode] = children
|
|
74
|
+
|
|
75
|
+
self._default_boxsize = default_boxsize
|
|
76
|
+
if isinstance(default_boxstyle, str):
|
|
77
|
+
default_boxstyle = dtheme.rectanglestyles.get(default_boxstyle)
|
|
78
|
+
self._default_boxstyle = default_boxstyle
|
|
79
|
+
self._default_box_r = default_box_r
|
|
80
|
+
self._default_box_horizontal_margin = default_box_horizontal_margin
|
|
81
|
+
self._default_box_vertical_margin = default_box_vertical_margin
|
|
82
|
+
|
|
83
|
+
if isinstance(default_textstyle, str):
|
|
84
|
+
default_textstyle = dtheme.rectangletextstyles.get(default_textstyle)
|
|
85
|
+
self._default_textstyle: Union[ShapeTextStyle, None] = default_textstyle
|
|
86
|
+
if isinstance(default_linestyle, str):
|
|
87
|
+
default_linestyle = dtheme.linestyles.get(default_linestyle)
|
|
88
|
+
self._default_linestyle: Union[LineStyle, None] = default_linestyle
|
|
89
|
+
|
|
90
|
+
self._default_line_horizontal_length = default_line_horizontal_length
|
|
91
|
+
self._default_line_vertical_length = default_line_vertical_length
|
|
92
|
+
|
|
93
|
+
self._drawing_item_name: Optional[str] = None
|
|
94
|
+
|
|
95
|
+
def draw(
|
|
96
|
+
self,
|
|
97
|
+
xy: Tuple[float, float],
|
|
98
|
+
orientation: Literal["horizontal", "vertical"],
|
|
99
|
+
align: Literal["top", "bottom", "center", "left", "right"],
|
|
100
|
+
) -> None:
|
|
101
|
+
"""Write docstring later."""
|
|
102
|
+
|
|
103
|
+
def _draw_vertical_left(
|
|
104
|
+
self,
|
|
105
|
+
xy: Tuple[float, float],
|
|
106
|
+
orientation: Literal["horizontal", "vertical"],
|
|
107
|
+
align: Literal["top", "bottom", "center", "left", "right"],
|
|
108
|
+
default_textstyle: ShapeTextStyle,
|
|
109
|
+
default_linestyle: LineStyle,
|
|
110
|
+
default_line_horizontal_margin: float,
|
|
111
|
+
default_line_horizontal_length: float,
|
|
112
|
+
default_line_vertical_margin: float,
|
|
113
|
+
) -> None:
|
|
114
|
+
"""Write doc string later."""
|
|
@@ -12,4 +12,7 @@
|
|
|
12
12
|
"""Smart art module."""
|
|
13
13
|
|
|
14
14
|
from drawlib.v0_2.private.smartarts.bubblespeech import bubblespeech
|
|
15
|
+
from drawlib.v0_2.private.smartarts.gridlayout import GridLayout
|
|
16
|
+
from drawlib.v0_2.private.smartarts.pyramid import Pyramid
|
|
15
17
|
from drawlib.v0_2.private.smartarts.sourcecode import SourceCode
|
|
18
|
+
from drawlib.v0_2.private.smartarts.tree import TreeNode
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
"""GridLayout implementation module."""
|
|
12
|
+
|
|
13
|
+
import dataclasses
|
|
14
|
+
from typing import List, Optional, Tuple, Union
|
|
15
|
+
|
|
16
|
+
from drawlib.v0_2.private.core.model import ShapeStyle, ShapeTextStyle
|
|
17
|
+
from drawlib.v0_2.private.core.theme import dtheme
|
|
18
|
+
from drawlib.v0_2.private.core_canvas.canvas import rectangle
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class GridLayout:
|
|
22
|
+
"""Class for rendering multiple rectangles which fit to grid."""
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
num_column: int,
|
|
27
|
+
num_row: int,
|
|
28
|
+
default_r: int = 0,
|
|
29
|
+
default_style: Union[str, ShapeStyle, None] = None,
|
|
30
|
+
default_textstyle: Union[str, ShapeTextStyle, None] = None,
|
|
31
|
+
) -> None:
|
|
32
|
+
"""Initialize class."""
|
|
33
|
+
self._num_column = num_column
|
|
34
|
+
self._num_row = num_row
|
|
35
|
+
self._default_r = default_r
|
|
36
|
+
if isinstance(default_style, str):
|
|
37
|
+
default_style = dtheme.rectanglestyles.get(default_style)
|
|
38
|
+
self._default_style = default_style
|
|
39
|
+
if isinstance(default_textstyle, str):
|
|
40
|
+
default_textstyle = dtheme.rectangletextstyles.get(default_textstyle)
|
|
41
|
+
self._default_textstyle = default_textstyle
|
|
42
|
+
|
|
43
|
+
self._items: List[_GridLayoutItem] = []
|
|
44
|
+
|
|
45
|
+
def add( # noqa: C901
|
|
46
|
+
self,
|
|
47
|
+
column_range: Tuple[int, int],
|
|
48
|
+
row_range: Tuple[int, int],
|
|
49
|
+
r: Optional[int] = None,
|
|
50
|
+
style: Union[str, ShapeStyle, None] = None,
|
|
51
|
+
text: str = "",
|
|
52
|
+
textstyle: Union[str, ShapeTextStyle, None] = None,
|
|
53
|
+
) -> None:
|
|
54
|
+
"""
|
|
55
|
+
Add an item to the grid layout.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
column_range (Tuple[int, int]): The range of columns the item will span.
|
|
59
|
+
row_range (Tuple[int, int]): The range of rows the item will span.
|
|
60
|
+
r (Optional[int], optional): The radius of the item. Default is None, which uses the default radius.
|
|
61
|
+
style (Union[str, ShapeStyle, None], optional):
|
|
62
|
+
The style of the item.
|
|
63
|
+
Can be a string key for a predefined style, a ShapeStyle object,
|
|
64
|
+
or None to use the default style.
|
|
65
|
+
text (str, optional): The text associated with the item. Default is an empty string.
|
|
66
|
+
textstyle (Union[str, ShapeTextStyle, None], optional):
|
|
67
|
+
The text style of the item. Can be a string key for a predefined text style,
|
|
68
|
+
a ShapeTextStyle object, or None to use the default text style.
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
ValueError: If the column or row ranges are invalid or out of bounds.
|
|
72
|
+
"""
|
|
73
|
+
# validate column
|
|
74
|
+
c1, c2 = column_range
|
|
75
|
+
if c1 > c2:
|
|
76
|
+
raise ValueError()
|
|
77
|
+
if c1 < 0:
|
|
78
|
+
raise ValueError()
|
|
79
|
+
if c2 > self._num_column:
|
|
80
|
+
raise ValueError()
|
|
81
|
+
|
|
82
|
+
# validate row
|
|
83
|
+
r1, r2 = row_range
|
|
84
|
+
if r1 > r2:
|
|
85
|
+
raise ValueError()
|
|
86
|
+
if r1 < 0:
|
|
87
|
+
raise ValueError()
|
|
88
|
+
if r2 > self._num_column:
|
|
89
|
+
raise ValueError()
|
|
90
|
+
|
|
91
|
+
# string style to Style class
|
|
92
|
+
if isinstance(style, str):
|
|
93
|
+
style = dtheme.rectanglestyles.get(style)
|
|
94
|
+
if isinstance(textstyle, str):
|
|
95
|
+
textstyle = dtheme.rectangletextstyles.get(textstyle)
|
|
96
|
+
|
|
97
|
+
# apply default if args are None
|
|
98
|
+
if r is None:
|
|
99
|
+
r = self._default_r
|
|
100
|
+
if style is None:
|
|
101
|
+
style = self._default_style
|
|
102
|
+
if textstyle is None:
|
|
103
|
+
textstyle = self._default_textstyle
|
|
104
|
+
|
|
105
|
+
# push
|
|
106
|
+
item = _GridLayoutItem(
|
|
107
|
+
column_range=column_range,
|
|
108
|
+
row_range=row_range,
|
|
109
|
+
r=r,
|
|
110
|
+
text=text,
|
|
111
|
+
style=style,
|
|
112
|
+
textstyle=textstyle,
|
|
113
|
+
)
|
|
114
|
+
self._items.append(item)
|
|
115
|
+
|
|
116
|
+
def draw(
|
|
117
|
+
self,
|
|
118
|
+
xy: Tuple[float, float],
|
|
119
|
+
width: float,
|
|
120
|
+
height: float,
|
|
121
|
+
margin: float,
|
|
122
|
+
outer_r: int = 0,
|
|
123
|
+
outer_style: Union[str, ShapeStyle, None] = None,
|
|
124
|
+
) -> None:
|
|
125
|
+
"""Draw the grid layout.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
xy (Tuple[float, float]): The x and y coordinates of the top-left corner of the grid.
|
|
129
|
+
width (float): The total width of the grid.
|
|
130
|
+
height (float): The total height of the grid.
|
|
131
|
+
margin (float): The margin between grid items.
|
|
132
|
+
outer_r (int, optional): The radius for the outer grid border. Default is 0.
|
|
133
|
+
outer_style (Union[str, ShapeStyle, None], optional):
|
|
134
|
+
The style for the outer grid border. Can be a string key for a predefined style,
|
|
135
|
+
a ShapeStyle object, or None.
|
|
136
|
+
"""
|
|
137
|
+
column_widths = [width / self._num_column] * self._num_column
|
|
138
|
+
row_heights = [height / self._num_row] * self._num_row
|
|
139
|
+
|
|
140
|
+
if outer_style is None:
|
|
141
|
+
column_margins = [margin] + [margin * 2] * (self._num_column - 1) + [margin]
|
|
142
|
+
row_margins = [margin] + [margin * 2] * (self._num_row - 1) + [margin]
|
|
143
|
+
else:
|
|
144
|
+
column_margins = [margin * 2] * (self._num_column + 1)
|
|
145
|
+
row_margins = [margin * 2] * (self._num_row + 1)
|
|
146
|
+
|
|
147
|
+
self.draw_flexible(
|
|
148
|
+
xy=xy,
|
|
149
|
+
column_widths=column_widths,
|
|
150
|
+
column_margins=column_margins,
|
|
151
|
+
row_heights=row_heights,
|
|
152
|
+
row_margins=row_margins,
|
|
153
|
+
outer_r=outer_r,
|
|
154
|
+
outer_style=outer_style,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
def draw_flexible( # noqa: C901
|
|
158
|
+
self,
|
|
159
|
+
xy: Tuple[float, float],
|
|
160
|
+
column_widths: List[float],
|
|
161
|
+
column_margins: List[float],
|
|
162
|
+
row_heights: List[float],
|
|
163
|
+
row_margins: List[float],
|
|
164
|
+
outer_r: int = 0,
|
|
165
|
+
outer_style: Union[str, ShapeStyle, None] = None,
|
|
166
|
+
) -> None:
|
|
167
|
+
"""Draw the grid layout with flexible column widths and row heights.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
xy (Tuple[float, float]): The x and y coordinates of the top-left corner of the grid.
|
|
171
|
+
column_widths (List[float]): The widths of each column.
|
|
172
|
+
column_margins (List[float]): The margins between columns.
|
|
173
|
+
row_heights (List[float]): The heights of each row.
|
|
174
|
+
row_margins (List[float]): The margins between rows.
|
|
175
|
+
outer_r (int, optional): The radius for the outer grid border. Default is 0.
|
|
176
|
+
outer_style (Union[str, ShapeStyle, None], optional):
|
|
177
|
+
The style for the outer grid border.
|
|
178
|
+
Can be a string key for a predefined style, a ShapeStyle object, or None.
|
|
179
|
+
|
|
180
|
+
Raises:
|
|
181
|
+
ValueError: If the lengths of column_widths, column_margins, row_heights, or row_margins are incorrect.
|
|
182
|
+
"""
|
|
183
|
+
# validate
|
|
184
|
+
if len(column_widths) != self._num_column:
|
|
185
|
+
raise ValueError()
|
|
186
|
+
if len(column_margins) != self._num_column + 1:
|
|
187
|
+
raise ValueError()
|
|
188
|
+
if len(row_heights) != self._num_row:
|
|
189
|
+
raise ValueError()
|
|
190
|
+
if len(row_margins) != self._num_row + 1:
|
|
191
|
+
raise ValueError()
|
|
192
|
+
|
|
193
|
+
# draw outer rectangle
|
|
194
|
+
if outer_style is not None:
|
|
195
|
+
if isinstance(outer_style, str):
|
|
196
|
+
outer_style = dtheme.rectanglestyles.get(outer_style)
|
|
197
|
+
outer_style.halign = "left"
|
|
198
|
+
outer_style.valign = "bottom"
|
|
199
|
+
rectangle(
|
|
200
|
+
xy=xy,
|
|
201
|
+
width=sum(column_widths),
|
|
202
|
+
height=sum(row_heights),
|
|
203
|
+
r=outer_r,
|
|
204
|
+
style=outer_style,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# utility
|
|
208
|
+
def sum_till_index(lst: List[float], index: int) -> float:
|
|
209
|
+
if index == 0:
|
|
210
|
+
return 0
|
|
211
|
+
return sum([lst[i] for i in range(index)])
|
|
212
|
+
|
|
213
|
+
for item in self._items:
|
|
214
|
+
column_range = item.column_range
|
|
215
|
+
row_range = item.row_range
|
|
216
|
+
r = item.r
|
|
217
|
+
style = item.style
|
|
218
|
+
text = item.text
|
|
219
|
+
textstyle = item.textstyle
|
|
220
|
+
|
|
221
|
+
cr0 = column_range[0]
|
|
222
|
+
cr1 = column_range[1]
|
|
223
|
+
rr0 = row_range[0]
|
|
224
|
+
rr1 = row_range[1]
|
|
225
|
+
|
|
226
|
+
# coordinate without margin
|
|
227
|
+
lb_xy = (sum_till_index(column_widths, cr0), sum_till_index(row_heights, rr0))
|
|
228
|
+
width = sum_till_index(column_widths, cr1 + 1) - lb_xy[0]
|
|
229
|
+
height = sum_till_index(row_heights, rr1 + 1) - lb_xy[1]
|
|
230
|
+
|
|
231
|
+
# get margins
|
|
232
|
+
margin_left = column_margins[cr0] if cr0 == 0 else column_margins[cr0] / 2
|
|
233
|
+
margin_right = column_margins[cr1 + 1] if cr1 + 1 == self._num_column else column_margins[cr1 + 1] / 2
|
|
234
|
+
margin_bottom = row_margins[rr0] if rr0 == 0 else row_margins[rr0] / 2
|
|
235
|
+
margin_top = row_margins[rr1 + 1] if rr1 + 1 == self._num_row else row_margins[rr1 + 1] / 2
|
|
236
|
+
|
|
237
|
+
# update coordinate
|
|
238
|
+
lb_xy = (lb_xy[0] + margin_left, lb_xy[1] + margin_bottom)
|
|
239
|
+
width = width - margin_left - margin_right
|
|
240
|
+
height = height - margin_bottom - margin_top
|
|
241
|
+
|
|
242
|
+
# set align left bottom
|
|
243
|
+
if style is None:
|
|
244
|
+
style = self._default_style
|
|
245
|
+
if style is None:
|
|
246
|
+
style = dtheme.rectanglestyles.get()
|
|
247
|
+
else:
|
|
248
|
+
style = style.copy()
|
|
249
|
+
style.halign = "left"
|
|
250
|
+
style.valign = "bottom"
|
|
251
|
+
|
|
252
|
+
# apply default text style if specified text style is None
|
|
253
|
+
if textstyle is None:
|
|
254
|
+
textstyle = self._default_textstyle
|
|
255
|
+
|
|
256
|
+
# draw
|
|
257
|
+
rectangle(
|
|
258
|
+
xy=(xy[0] + lb_xy[0], xy[1] + lb_xy[1]),
|
|
259
|
+
width=width,
|
|
260
|
+
height=height,
|
|
261
|
+
r=r,
|
|
262
|
+
style=style,
|
|
263
|
+
text=text,
|
|
264
|
+
textstyle=textstyle,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
@dataclasses.dataclass
|
|
269
|
+
class _GridLayoutItem:
|
|
270
|
+
column_range: Tuple[int, int]
|
|
271
|
+
row_range: Tuple[int, int]
|
|
272
|
+
r: int
|
|
273
|
+
style: Optional[ShapeStyle]
|
|
274
|
+
text: str
|
|
275
|
+
textstyle: Optional[ShapeTextStyle]
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
"""Pyramid implementation module."""
|
|
12
|
+
|
|
13
|
+
import dataclasses
|
|
14
|
+
from typing import List, Optional, Tuple, Union
|
|
15
|
+
|
|
16
|
+
from drawlib.v0_2.private.core.model import ShapeStyle, ShapeTextStyle
|
|
17
|
+
from drawlib.v0_2.private.core.theme import dtheme
|
|
18
|
+
from drawlib.v0_2.private.core_canvas.canvas import trapezoid, triangle
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Pyramid:
|
|
22
|
+
"""Class for rendering smart art pyramid."""
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
default_style: Union[str, ShapeStyle, None] = None,
|
|
27
|
+
default_textstyle: Union[str, ShapeTextStyle, None] = None,
|
|
28
|
+
) -> None:
|
|
29
|
+
"""Initialize class."""
|
|
30
|
+
if isinstance(default_style, str):
|
|
31
|
+
default_style = dtheme.rectanglestyles.get(default_style)
|
|
32
|
+
self._default_style = default_style
|
|
33
|
+
if isinstance(default_textstyle, str):
|
|
34
|
+
default_textstyle = dtheme.rectangletextstyles.get(default_textstyle)
|
|
35
|
+
self._default_textstyle = default_textstyle
|
|
36
|
+
|
|
37
|
+
self._items: List[_PyramidItem] = []
|
|
38
|
+
|
|
39
|
+
def add( # noqa: C901
|
|
40
|
+
self,
|
|
41
|
+
style: Union[str, ShapeStyle, None] = None,
|
|
42
|
+
text: str = "",
|
|
43
|
+
textstyle: Union[str, ShapeTextStyle, None] = None,
|
|
44
|
+
) -> None:
|
|
45
|
+
"""
|
|
46
|
+
Add an item to the pyramid.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
style (Union[str, ShapeStyle, None], optional):
|
|
50
|
+
The style of the item.
|
|
51
|
+
Can be a string key for a predefined style, a ShapeStyle object,
|
|
52
|
+
or None to use the default style.
|
|
53
|
+
text (str, optional): The text associated with the item. Default is an empty string.
|
|
54
|
+
textstyle (Union[str, ShapeTextStyle, None], optional):
|
|
55
|
+
The text style of the item. Can be a string key for a predefined text style,
|
|
56
|
+
a ShapeTextStyle object, or None to use the default text style.
|
|
57
|
+
"""
|
|
58
|
+
# string style to Style class
|
|
59
|
+
if isinstance(style, str):
|
|
60
|
+
style = dtheme.rectanglestyles.get(style)
|
|
61
|
+
if isinstance(textstyle, str):
|
|
62
|
+
textstyle = dtheme.rectangletextstyles.get(textstyle)
|
|
63
|
+
|
|
64
|
+
# apply default if args are None
|
|
65
|
+
if style is None:
|
|
66
|
+
style = self._default_style
|
|
67
|
+
if textstyle is None:
|
|
68
|
+
textstyle = self._default_textstyle
|
|
69
|
+
|
|
70
|
+
# push
|
|
71
|
+
item = _PyramidItem(
|
|
72
|
+
text=text,
|
|
73
|
+
style=style,
|
|
74
|
+
textstyle=textstyle,
|
|
75
|
+
)
|
|
76
|
+
self._items.append(item)
|
|
77
|
+
|
|
78
|
+
def draw(
|
|
79
|
+
self,
|
|
80
|
+
xy: Tuple[float, float],
|
|
81
|
+
width: float,
|
|
82
|
+
height: float,
|
|
83
|
+
margin: float,
|
|
84
|
+
) -> None:
|
|
85
|
+
"""Draw smart art pyramid.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
xy (Tuple[float, float]): The x and y coordinates of the bottom-left corner of the pyramid.
|
|
89
|
+
width (float): The width of the pyramid.
|
|
90
|
+
height (float): The heifht of the pyramid.
|
|
91
|
+
margin (float): The margin between pyramid items.
|
|
92
|
+
"""
|
|
93
|
+
if len(self._items) == 0:
|
|
94
|
+
raise ValueError()
|
|
95
|
+
|
|
96
|
+
margins = [margin] * (len(self._items) - 1)
|
|
97
|
+
item_height = (height - sum(margins)) / len(self._items)
|
|
98
|
+
item_heights = [item_height] * len(self._items)
|
|
99
|
+
|
|
100
|
+
self.draw_flexible(
|
|
101
|
+
xy=xy,
|
|
102
|
+
width=width,
|
|
103
|
+
item_heights=item_heights,
|
|
104
|
+
margins=margins,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
def draw_flexible( # noqa: C901
|
|
108
|
+
self,
|
|
109
|
+
xy: Tuple[float, float],
|
|
110
|
+
width: float,
|
|
111
|
+
item_heights: List[float],
|
|
112
|
+
margins: List[float],
|
|
113
|
+
) -> None:
|
|
114
|
+
"""Draw smart art pyramid with flexible pyramid item heights.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
xy (Tuple[float, float]): The x and y coordinates of the bottom-left corner of the pyramid.
|
|
118
|
+
width (float): The width of the pyramid.
|
|
119
|
+
item_heights (float): The height of the each pyramid items.
|
|
120
|
+
margins (float): The margin between pyramid items.
|
|
121
|
+
|
|
122
|
+
Raises:
|
|
123
|
+
ValueError: If the lengths of column_widths, column_margins, row_heights, or row_margins are incorrect.
|
|
124
|
+
"""
|
|
125
|
+
# validate
|
|
126
|
+
if len(self._items) == 0:
|
|
127
|
+
raise ValueError()
|
|
128
|
+
|
|
129
|
+
if len(self._items) != len(item_heights):
|
|
130
|
+
raise ValueError()
|
|
131
|
+
|
|
132
|
+
if len(self._items) != len(margins) + 1:
|
|
133
|
+
raise ValueError()
|
|
134
|
+
|
|
135
|
+
x = xy[0] + width / 2
|
|
136
|
+
height = sum(item_heights) + sum(margins)
|
|
137
|
+
current_height = 0
|
|
138
|
+
for i, item in enumerate(self._items):
|
|
139
|
+
text = item.text
|
|
140
|
+
textstyle = item.textstyle
|
|
141
|
+
if textstyle is None:
|
|
142
|
+
textstyle = self._default_textstyle
|
|
143
|
+
style = item.style
|
|
144
|
+
if style is None:
|
|
145
|
+
style = self._default_style
|
|
146
|
+
if style is None:
|
|
147
|
+
style = dtheme.rectanglestyles.get()
|
|
148
|
+
else:
|
|
149
|
+
style = style.copy()
|
|
150
|
+
style.halign = "center"
|
|
151
|
+
style.valign = "bottom"
|
|
152
|
+
|
|
153
|
+
is_last = i == len(self._items) - 1
|
|
154
|
+
if is_last:
|
|
155
|
+
ratio = (height - current_height) / height
|
|
156
|
+
item_width = ratio * width
|
|
157
|
+
item_height = item_heights[i]
|
|
158
|
+
triangle(
|
|
159
|
+
(x, xy[1] + current_height),
|
|
160
|
+
width=item_width,
|
|
161
|
+
height=item_height,
|
|
162
|
+
style=style,
|
|
163
|
+
text=text,
|
|
164
|
+
textstyle=textstyle,
|
|
165
|
+
)
|
|
166
|
+
continue
|
|
167
|
+
|
|
168
|
+
bottom_ratio = (height - current_height) / height
|
|
169
|
+
bottom_width = bottom_ratio * width
|
|
170
|
+
item_height = item_heights[i]
|
|
171
|
+
top_ratio = (height - current_height - item_height) / height
|
|
172
|
+
top_width = top_ratio * width
|
|
173
|
+
trapezoid(
|
|
174
|
+
(x, xy[1] + current_height),
|
|
175
|
+
item_height,
|
|
176
|
+
bottomedge_width=bottom_width,
|
|
177
|
+
topedge_width=top_width,
|
|
178
|
+
style=style,
|
|
179
|
+
text=text,
|
|
180
|
+
textstyle=textstyle,
|
|
181
|
+
)
|
|
182
|
+
current_height += item_height + margins[i]
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@dataclasses.dataclass
|
|
186
|
+
class _PyramidItem:
|
|
187
|
+
style: Optional[ShapeStyle]
|
|
188
|
+
text: str
|
|
189
|
+
textstyle: Optional[ShapeTextStyle]
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
"""Tree implementation module."""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import dataclasses
|
|
16
|
+
from typing import Callable, Dict, List, Literal, Optional, Tuple, Union
|
|
17
|
+
|
|
18
|
+
from drawlib.v0_2.private.core.model import IconStyle, ImageStyle, LineStyle, ShapeStyle, TextStyle
|
|
19
|
+
from drawlib.v0_2.private.core.theme import dtheme
|
|
20
|
+
from drawlib.v0_2.private.core_canvas.canvas import line, text
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TreeNode:
|
|
24
|
+
"""Class for rendering smart art Tree."""
|
|
25
|
+
|
|
26
|
+
_drawing_item_map: Dict[str, _TreeNodeDrawingItem] = {}
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
text: str,
|
|
31
|
+
textstyle: Union[str, TextStyle, None] = None,
|
|
32
|
+
linestyle: Union[str, LineStyle, None] = None,
|
|
33
|
+
line_horizontal_margin: Optional[float] = None,
|
|
34
|
+
line_horizontal_length: Optional[float] = None,
|
|
35
|
+
line_vertical_margin: Optional[float] = None,
|
|
36
|
+
children: Optional[List[TreeNode]] = None,
|
|
37
|
+
default_textstyle: Union[str, TextStyle, None] = None,
|
|
38
|
+
default_linestyle: Union[str, LineStyle, None] = None,
|
|
39
|
+
default_line_horizontal_margin: Optional[float] = None,
|
|
40
|
+
default_line_horizontal_length: Optional[float] = None,
|
|
41
|
+
default_line_vertical_margin: Optional[float] = None,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Initialize class."""
|
|
44
|
+
self._text = text
|
|
45
|
+
|
|
46
|
+
if isinstance(textstyle, str):
|
|
47
|
+
textstyle = dtheme.textstyles.get(textstyle)
|
|
48
|
+
self._textstyle = textstyle
|
|
49
|
+
if isinstance(linestyle, str):
|
|
50
|
+
linestyle = dtheme.linestyles.get(linestyle)
|
|
51
|
+
self._linestyle = linestyle
|
|
52
|
+
|
|
53
|
+
self._line_horizontal_margin = line_horizontal_margin
|
|
54
|
+
self._line_horizontal_length = line_horizontal_length
|
|
55
|
+
self._line_vertical_margin = line_vertical_margin
|
|
56
|
+
|
|
57
|
+
if children is None:
|
|
58
|
+
self._children: List[TreeNode] = []
|
|
59
|
+
else:
|
|
60
|
+
self._children: List[TreeNode] = children
|
|
61
|
+
|
|
62
|
+
if isinstance(default_textstyle, str):
|
|
63
|
+
default_textstyle = dtheme.textstyles.get(default_textstyle)
|
|
64
|
+
self._default_textstyle: Union[TextStyle, None] = default_textstyle
|
|
65
|
+
if isinstance(default_linestyle, str):
|
|
66
|
+
default_linestyle = dtheme.linestyles.get(default_linestyle)
|
|
67
|
+
self._default_linestyle: Union[LineStyle, None] = default_linestyle
|
|
68
|
+
|
|
69
|
+
self._default_line_horizontal_margin: Optional[float] = default_line_horizontal_margin
|
|
70
|
+
self._default_line_horizontal_length: Optional[float] = default_line_horizontal_length
|
|
71
|
+
self._default_line_vertical_margin: Optional[float] = default_line_vertical_margin
|
|
72
|
+
|
|
73
|
+
self._drawing_item_name: Optional[str] = None
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def register_drawing_item(
|
|
77
|
+
cls,
|
|
78
|
+
name: str,
|
|
79
|
+
location: Literal["before", "after"],
|
|
80
|
+
padding_width: float,
|
|
81
|
+
function: Callable,
|
|
82
|
+
style: Union[IconStyle, ImageStyle, ShapeStyle, TextStyle],
|
|
83
|
+
args: dict,
|
|
84
|
+
) -> None:
|
|
85
|
+
"""Register a drawing item for the tree node.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
name (str): Name of drawing item.
|
|
89
|
+
location (Literal["before", "after"]): The location of the drawing item relative to the text.
|
|
90
|
+
padding_width (float): The padding width for the drawing item.
|
|
91
|
+
function (Callable): The function to render the drawing item.
|
|
92
|
+
style (Union[IconStyle, ImageStyle, ShapeStyle, TextStyle]): The style for the drawing item.
|
|
93
|
+
args (dict): The arguments for the function.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
TreeNode: The current tree node instance.
|
|
97
|
+
"""
|
|
98
|
+
style.halign = "left"
|
|
99
|
+
style.valign = "center"
|
|
100
|
+
|
|
101
|
+
item = _TreeNodeDrawingItem(
|
|
102
|
+
location=location,
|
|
103
|
+
padding_width=padding_width,
|
|
104
|
+
function=function,
|
|
105
|
+
style=style,
|
|
106
|
+
args=args,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
cls._drawing_item_map[name] = item
|
|
110
|
+
|
|
111
|
+
def set_drawing_item(
|
|
112
|
+
self,
|
|
113
|
+
name: str,
|
|
114
|
+
) -> TreeNode:
|
|
115
|
+
"""Set a drawing item for the tree node.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
name (str): Name of drawing item.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
TreeNode: The current tree node instance.
|
|
122
|
+
"""
|
|
123
|
+
if name not in self._drawing_item_map:
|
|
124
|
+
raise ValueError(f'Drawing item "{name}" is not registered.')
|
|
125
|
+
self._drawing_item_name = name
|
|
126
|
+
|
|
127
|
+
return self
|
|
128
|
+
|
|
129
|
+
def draw(self, xy: Tuple[float, float]) -> None:
|
|
130
|
+
"""Draw the tree node and its children.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
xy (Tuple[float, float]): The coordinates to start drawing.
|
|
134
|
+
|
|
135
|
+
Raises:
|
|
136
|
+
ValueError: If any of the default styles or margins are None.
|
|
137
|
+
"""
|
|
138
|
+
if self._default_textstyle is None:
|
|
139
|
+
raise ValueError()
|
|
140
|
+
if self._default_linestyle is None:
|
|
141
|
+
raise ValueError()
|
|
142
|
+
if self._default_line_horizontal_margin is None:
|
|
143
|
+
raise ValueError()
|
|
144
|
+
if self._default_line_horizontal_length is None:
|
|
145
|
+
raise ValueError()
|
|
146
|
+
if self._default_line_vertical_margin is None:
|
|
147
|
+
raise ValueError()
|
|
148
|
+
|
|
149
|
+
self._draw(
|
|
150
|
+
xy=xy,
|
|
151
|
+
default_textstyle=self._default_textstyle,
|
|
152
|
+
default_linestyle=self._default_linestyle,
|
|
153
|
+
default_line_horizontal_margin=self._default_line_horizontal_margin,
|
|
154
|
+
default_line_horizontal_length=self._default_line_horizontal_length,
|
|
155
|
+
default_line_vertical_margin=self._default_line_vertical_margin,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
def _draw( # noqa: C901
|
|
159
|
+
self,
|
|
160
|
+
xy: Tuple[float, float],
|
|
161
|
+
default_textstyle: TextStyle,
|
|
162
|
+
default_linestyle: LineStyle,
|
|
163
|
+
default_line_horizontal_margin: float,
|
|
164
|
+
default_line_horizontal_length: float,
|
|
165
|
+
default_line_vertical_margin: float,
|
|
166
|
+
) -> float:
|
|
167
|
+
"""Draw the tree node and its children (internal method).
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
xy (Tuple[float, float]): The coordinates to start drawing.
|
|
171
|
+
default_textstyle (TextStyle): The default text style.
|
|
172
|
+
default_linestyle (LineStyle): The default line style.
|
|
173
|
+
default_line_horizontal_margin (float): The default horizontal line margin.
|
|
174
|
+
default_line_horizontal_length (float): The default horizontal line length.
|
|
175
|
+
default_line_vertical_margin (float): The default vertical line margin.
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
float: The y-coordinate after drawing the node and its children.
|
|
179
|
+
"""
|
|
180
|
+
# update default values
|
|
181
|
+
if self._default_textstyle is not None:
|
|
182
|
+
default_textstyle = self._default_textstyle
|
|
183
|
+
if self._default_linestyle is not None:
|
|
184
|
+
default_linestyle = self._default_linestyle
|
|
185
|
+
if self._default_line_horizontal_margin is not None:
|
|
186
|
+
default_line_horizontal_margin = self._default_line_horizontal_margin
|
|
187
|
+
if self._default_line_horizontal_length is not None:
|
|
188
|
+
default_line_horizontal_length = self._default_line_horizontal_length
|
|
189
|
+
if self._default_line_vertical_margin is not None:
|
|
190
|
+
default_line_vertical_margin = self._default_line_vertical_margin
|
|
191
|
+
|
|
192
|
+
# update values
|
|
193
|
+
textstyle = self._textstyle if self._textstyle is not None else default_textstyle
|
|
194
|
+
linestyle = self._linestyle if self._linestyle is not None else default_linestyle
|
|
195
|
+
if self._line_horizontal_margin is not None:
|
|
196
|
+
line_horizontal_margin = self._line_horizontal_margin
|
|
197
|
+
else:
|
|
198
|
+
line_horizontal_margin = default_line_horizontal_margin
|
|
199
|
+
if self._line_horizontal_length is not None:
|
|
200
|
+
line_horizontal_length = self._line_horizontal_length
|
|
201
|
+
else:
|
|
202
|
+
line_horizontal_length = default_line_horizontal_length
|
|
203
|
+
if self._line_vertical_margin is not None:
|
|
204
|
+
line_vertical_margin = self._line_vertical_margin
|
|
205
|
+
else:
|
|
206
|
+
line_vertical_margin = default_line_vertical_margin
|
|
207
|
+
|
|
208
|
+
# draw text
|
|
209
|
+
if self._drawing_item_name is None:
|
|
210
|
+
textstyle.halign = "left"
|
|
211
|
+
text(xy=xy, text=self._text, style=textstyle)
|
|
212
|
+
|
|
213
|
+
else:
|
|
214
|
+
drawing_item = self._drawing_item_map[self._drawing_item_name]
|
|
215
|
+
|
|
216
|
+
if drawing_item.location == "before":
|
|
217
|
+
args = drawing_item.args
|
|
218
|
+
args["xy"] = xy
|
|
219
|
+
args["style"] = drawing_item.style
|
|
220
|
+
drawing_item.function(**args)
|
|
221
|
+
|
|
222
|
+
textstyle.halign = "left"
|
|
223
|
+
text(xy=(xy[0] + drawing_item.padding_width, xy[1]), text=self._text, style=textstyle)
|
|
224
|
+
|
|
225
|
+
else:
|
|
226
|
+
textstyle.halign = "left"
|
|
227
|
+
text(xy=xy, text=self._text, style=textstyle)
|
|
228
|
+
|
|
229
|
+
args = drawing_item.args
|
|
230
|
+
args["xy"] = (xy[0] + drawing_item.padding_width, xy[1])
|
|
231
|
+
args["style"] = drawing_item.style
|
|
232
|
+
drawing_item.function(**args)
|
|
233
|
+
|
|
234
|
+
# draw children
|
|
235
|
+
horizontal_line_x1 = xy[0] + line_horizontal_margin
|
|
236
|
+
horizontal_line_x2 = horizontal_line_x1 + line_horizontal_length * 2 / 3
|
|
237
|
+
child_x = horizontal_line_x1 + line_horizontal_margin
|
|
238
|
+
child_y = xy[1]
|
|
239
|
+
child_y_previous = child_y
|
|
240
|
+
for child in self._children:
|
|
241
|
+
child_y -= line_vertical_margin
|
|
242
|
+
# draw child horizontal line
|
|
243
|
+
line(
|
|
244
|
+
xy1=(horizontal_line_x1, child_y),
|
|
245
|
+
xy2=(horizontal_line_x2, child_y),
|
|
246
|
+
style=linestyle,
|
|
247
|
+
)
|
|
248
|
+
# draw child
|
|
249
|
+
child_y_previous = child_y
|
|
250
|
+
child_y = child._draw(
|
|
251
|
+
xy=(child_x, child_y),
|
|
252
|
+
default_textstyle=default_textstyle,
|
|
253
|
+
default_linestyle=default_linestyle,
|
|
254
|
+
default_line_horizontal_margin=default_line_horizontal_margin,
|
|
255
|
+
default_line_horizontal_length=default_line_horizontal_length,
|
|
256
|
+
default_line_vertical_margin=default_line_vertical_margin,
|
|
257
|
+
)
|
|
258
|
+
# draw children vertical line
|
|
259
|
+
if xy[1] != child_y_previous:
|
|
260
|
+
line(
|
|
261
|
+
(horizontal_line_x1, xy[1] - line_vertical_margin / 2),
|
|
262
|
+
(horizontal_line_x1, child_y_previous),
|
|
263
|
+
style=linestyle,
|
|
264
|
+
)
|
|
265
|
+
return child_y
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
@dataclasses.dataclass
|
|
269
|
+
class _TreeNodeDrawingItem:
|
|
270
|
+
location: Literal["before", "after"]
|
|
271
|
+
padding_width: float
|
|
272
|
+
function: Callable
|
|
273
|
+
style: Union[IconStyle, ImageStyle, ShapeStyle, TextStyle]
|
|
274
|
+
args: dict
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
"""Activity diagram implementation module."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
"""Class diagram implementation module."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
"""Communication diagram implementation module."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
"""Component diagram implementation module."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
"""Deployment diagram implementation module."""
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
# ruff: noqa: F401
|
|
11
|
+
|
|
12
|
+
"""UML module."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
"""Object diagram implementation module."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
"""Package diagram implementation module."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
"""Sequence diagram implementation module."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
"""State Machine diagram implementation module."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright (c) 2024 Yuichi Ito (yuichi@yuichi.com)
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the Apache License, Version 2.0.
|
|
4
|
+
# For more information, please visit: https://github.com/yuichi110/drawlib
|
|
5
|
+
#
|
|
6
|
+
# This software is provided "as is", without warranty of any kind,
|
|
7
|
+
# express or implied, including but not limited to the warranties of
|
|
8
|
+
# merchantability, fitness for a particular purpose and noninfringement.
|
|
9
|
+
|
|
10
|
+
"""Usecase diagram implementation module."""
|
|
@@ -7,7 +7,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
7
7
|
|
|
8
8
|
[tool.poetry]
|
|
9
9
|
name = "drawlib"
|
|
10
|
-
version = "0.2.
|
|
10
|
+
version = "0.2.3.dev1"
|
|
11
11
|
description = "Python drawing library. Illustration as Code."
|
|
12
12
|
homepage = "https://www.drawlib.com"
|
|
13
13
|
repository = "https://github.com/yuichi110/drawlib"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|