1# Copyright (c) 2010-2024 openpyxl
2
3from openpyxl.descriptors.serialisable import Serialisable
4from openpyxl.descriptors import (
5 Typed,
6 Integer,
7 MinMax,
8 NoneSet,
9 Alias,
10 Sequence
11)
12
13from openpyxl.descriptors.nested import (
14 NestedInteger,
15 NestedNoneSet,
16 EmptyTag,
17)
18from openpyxl.xml.constants import DRAWING_NS
19
20from .colors import ColorChoiceDescriptor
21from .fill import GradientFillProperties, PatternFillProperties
22from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
23
24"""
25Line elements from drawing main schema
26"""
27
28
29class LineEndProperties(Serialisable):
30
31 tagname = "end"
32 namespace = DRAWING_NS
33
34 type = NoneSet(values=(['none', 'triangle', 'stealth', 'diamond', 'oval', 'arrow']))
35 w = NoneSet(values=(['sm', 'med', 'lg']))
36 len = NoneSet(values=(['sm', 'med', 'lg']))
37
38 def __init__(self,
39 type=None,
40 w=None,
41 len=None,
42 ):
43 self.type = type
44 self.w = w
45 self.len = len
46
47
48class DashStop(Serialisable):
49
50 tagname = "ds"
51 namespace = DRAWING_NS
52
53 d = Integer()
54 length = Alias('d')
55 sp = Integer()
56 space = Alias('sp')
57
58 def __init__(self,
59 d=0,
60 sp=0,
61 ):
62 self.d = d
63 self.sp = sp
64
65
66class DashStopList(Serialisable):
67
68 ds = Sequence(expected_type=DashStop, allow_none=True)
69
70 def __init__(self,
71 ds=None,
72 ):
73 self.ds = ds
74
75
76class LineProperties(Serialisable):
77
78 tagname = "ln"
79 namespace = DRAWING_NS
80
81 w = MinMax(min=0, max=20116800, allow_none=True) # EMU
82 width = Alias('w')
83 cap = NoneSet(values=(['rnd', 'sq', 'flat']))
84 cmpd = NoneSet(values=(['sng', 'dbl', 'thickThin', 'thinThick', 'tri']))
85 algn = NoneSet(values=(['ctr', 'in']))
86
87 noFill = EmptyTag()
88 solidFill = ColorChoiceDescriptor()
89 gradFill = Typed(expected_type=GradientFillProperties, allow_none=True)
90 pattFill = Typed(expected_type=PatternFillProperties, allow_none=True)
91
92 prstDash = NestedNoneSet(values=(['solid', 'dot', 'dash', 'lgDash', 'dashDot',
93 'lgDashDot', 'lgDashDotDot', 'sysDash', 'sysDot', 'sysDashDot',
94 'sysDashDotDot']), namespace=namespace)
95 dashStyle = Alias('prstDash')
96
97 custDash = Typed(expected_type=DashStop, allow_none=True)
98
99 round = EmptyTag()
100 bevel = EmptyTag()
101 miter = NestedInteger(allow_none=True, attribute="lim")
102
103 headEnd = Typed(expected_type=LineEndProperties, allow_none=True)
104 tailEnd = Typed(expected_type=LineEndProperties, allow_none=True)
105 extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
106
107 __elements__ = ('noFill', 'solidFill', 'gradFill', 'pattFill',
108 'prstDash', 'custDash', 'round', 'bevel', 'miter', 'headEnd', 'tailEnd')
109
110 def __init__(self,
111 w=None,
112 cap=None,
113 cmpd=None,
114 algn=None,
115 noFill=None,
116 solidFill=None,
117 gradFill=None,
118 pattFill=None,
119 prstDash=None,
120 custDash=None,
121 round=None,
122 bevel=None,
123 miter=None,
124 headEnd=None,
125 tailEnd=None,
126 extLst=None,
127 ):
128 self.w = w
129 self.cap = cap
130 self.cmpd = cmpd
131 self.algn = algn
132 self.noFill = noFill
133 self.solidFill = solidFill
134 self.gradFill = gradFill
135 self.pattFill = pattFill
136 if prstDash is None:
137 prstDash = "solid"
138 self.prstDash = prstDash
139 self.custDash = custDash
140 self.round = round
141 self.bevel = bevel
142 self.miter = miter
143 self.headEnd = headEnd
144 self.tailEnd = tailEnd