python-pptx2 2.13.0__py3-none-any.whl

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.
Files changed (175) hide show
  1. pptx2/__init__.py +152 -0
  2. pptx2/_color.py +75 -0
  3. pptx2/_slide_importer.py +597 -0
  4. pptx2/_svg.py +155 -0
  5. pptx2/_template_applier.py +292 -0
  6. pptx2/_textstyle.py +187 -0
  7. pptx2/accessibility.py +365 -0
  8. pptx2/action.py +270 -0
  9. pptx2/animation.py +2237 -0
  10. pptx2/api.py +49 -0
  11. pptx2/audit.py +258 -0
  12. pptx2/chart/__init__.py +0 -0
  13. pptx2/chart/analytics.py +381 -0
  14. pptx2/chart/axis.py +543 -0
  15. pptx2/chart/category.py +200 -0
  16. pptx2/chart/chart.py +670 -0
  17. pptx2/chart/data.py +864 -0
  18. pptx2/chart/datalabel.py +406 -0
  19. pptx2/chart/legend.py +86 -0
  20. pptx2/chart/marker.py +70 -0
  21. pptx2/chart/palettes.py +129 -0
  22. pptx2/chart/plot.py +462 -0
  23. pptx2/chart/point.py +101 -0
  24. pptx2/chart/quick_layouts.py +325 -0
  25. pptx2/chart/series.py +334 -0
  26. pptx2/chart/xlsx.py +272 -0
  27. pptx2/chart/xmlwriter.py +1845 -0
  28. pptx2/compose/__init__.py +28 -0
  29. pptx2/compose/from_spec.py +1094 -0
  30. pptx2/design/__init__.py +8 -0
  31. pptx2/design/components.py +607 -0
  32. pptx2/design/figures.py +389 -0
  33. pptx2/design/layout.py +370 -0
  34. pptx2/design/recipes.py +1967 -0
  35. pptx2/design/style.py +209 -0
  36. pptx2/design/tokens.py +915 -0
  37. pptx2/diagrams.py +754 -0
  38. pptx2/dml/__init__.py +0 -0
  39. pptx2/dml/chtfmt.py +40 -0
  40. pptx2/dml/color.py +496 -0
  41. pptx2/dml/effect.py +909 -0
  42. pptx2/dml/fill.py +691 -0
  43. pptx2/dml/line.py +287 -0
  44. pptx2/dml/picture.py +212 -0
  45. pptx2/dml/three_d.py +381 -0
  46. pptx2/enum/__init__.py +0 -0
  47. pptx2/enum/action.py +71 -0
  48. pptx2/enum/animation.py +31 -0
  49. pptx2/enum/base.py +218 -0
  50. pptx2/enum/chart.py +574 -0
  51. pptx2/enum/dml.py +740 -0
  52. pptx2/enum/lang.py +685 -0
  53. pptx2/enum/presentation.py +133 -0
  54. pptx2/enum/shapes.py +1029 -0
  55. pptx2/enum/text.py +230 -0
  56. pptx2/exc.py +42 -0
  57. pptx2/formats.py +139 -0
  58. pptx2/geometry.py +420 -0
  59. pptx2/inherit.py +109 -0
  60. pptx2/lint.py +2256 -0
  61. pptx2/math.py +177 -0
  62. pptx2/media.py +197 -0
  63. pptx2/opc/__init__.py +0 -0
  64. pptx2/opc/constants.py +332 -0
  65. pptx2/opc/oxml.py +188 -0
  66. pptx2/opc/package.py +762 -0
  67. pptx2/opc/packuri.py +109 -0
  68. pptx2/opc/serialized.py +296 -0
  69. pptx2/opc/shared.py +20 -0
  70. pptx2/opc/spec.py +45 -0
  71. pptx2/oxml/__init__.py +555 -0
  72. pptx2/oxml/action.py +53 -0
  73. pptx2/oxml/chart/__init__.py +0 -0
  74. pptx2/oxml/chart/axis.py +337 -0
  75. pptx2/oxml/chart/chart.py +481 -0
  76. pptx2/oxml/chart/datalabel.py +253 -0
  77. pptx2/oxml/chart/legend.py +72 -0
  78. pptx2/oxml/chart/marker.py +61 -0
  79. pptx2/oxml/chart/plot.py +365 -0
  80. pptx2/oxml/chart/series.py +425 -0
  81. pptx2/oxml/chart/shared.py +220 -0
  82. pptx2/oxml/coreprops.py +288 -0
  83. pptx2/oxml/dml/__init__.py +0 -0
  84. pptx2/oxml/dml/color.py +135 -0
  85. pptx2/oxml/dml/effect.py +213 -0
  86. pptx2/oxml/dml/fill.py +316 -0
  87. pptx2/oxml/dml/line.py +12 -0
  88. pptx2/oxml/dml/three_d.py +110 -0
  89. pptx2/oxml/ns.py +135 -0
  90. pptx2/oxml/presentation.py +313 -0
  91. pptx2/oxml/shapes/__init__.py +19 -0
  92. pptx2/oxml/shapes/autoshape.py +467 -0
  93. pptx2/oxml/shapes/connector.py +107 -0
  94. pptx2/oxml/shapes/graphfrm.py +347 -0
  95. pptx2/oxml/shapes/groupshape.py +329 -0
  96. pptx2/oxml/shapes/picture.py +270 -0
  97. pptx2/oxml/shapes/shared.py +577 -0
  98. pptx2/oxml/simpletypes.py +1027 -0
  99. pptx2/oxml/slide.py +563 -0
  100. pptx2/oxml/table.py +650 -0
  101. pptx2/oxml/text.py +815 -0
  102. pptx2/oxml/theme.py +36 -0
  103. pptx2/oxml/xmlchemy.py +717 -0
  104. pptx2/package.py +222 -0
  105. pptx2/parts/__init__.py +0 -0
  106. pptx2/parts/chart.py +95 -0
  107. pptx2/parts/coreprops.py +167 -0
  108. pptx2/parts/diagram.py +37 -0
  109. pptx2/parts/embeddedpackage.py +93 -0
  110. pptx2/parts/image.py +275 -0
  111. pptx2/parts/media.py +37 -0
  112. pptx2/parts/presentation.py +136 -0
  113. pptx2/parts/slide.py +371 -0
  114. pptx2/presentation.py +408 -0
  115. pptx2/py.typed +0 -0
  116. pptx2/render.py +586 -0
  117. pptx2/section.py +272 -0
  118. pptx2/shapes/__init__.py +26 -0
  119. pptx2/shapes/autoshape.py +442 -0
  120. pptx2/shapes/base.py +1078 -0
  121. pptx2/shapes/connector.py +297 -0
  122. pptx2/shapes/freeform.py +337 -0
  123. pptx2/shapes/graphfrm.py +316 -0
  124. pptx2/shapes/group.py +264 -0
  125. pptx2/shapes/picture.py +422 -0
  126. pptx2/shapes/placeholder.py +468 -0
  127. pptx2/shapes/shapetree.py +2027 -0
  128. pptx2/shared.py +82 -0
  129. pptx2/skill/SKILL.md +450 -0
  130. pptx2/skill/__init__.py +78 -0
  131. pptx2/skill/__main__.py +64 -0
  132. pptx2/skill/references/animations.md +189 -0
  133. pptx2/skill/references/basics.md +421 -0
  134. pptx2/skill/references/charts.md +254 -0
  135. pptx2/skill/references/compose.md +234 -0
  136. pptx2/skill/references/design.md +366 -0
  137. pptx2/skill/references/effects.md +249 -0
  138. pptx2/skill/references/end-to-end-deck.md +231 -0
  139. pptx2/skill/references/geometry-and-arrows.md +334 -0
  140. pptx2/skill/references/lint.md +275 -0
  141. pptx2/skill/references/math.md +86 -0
  142. pptx2/skill/references/picture-effects.md +129 -0
  143. pptx2/skill/references/render.md +151 -0
  144. pptx2/skill/references/smart-art.md +75 -0
  145. pptx2/skill/references/space-aware-authoring.md +249 -0
  146. pptx2/skill/references/tables.md +244 -0
  147. pptx2/skill/references/theme.md +127 -0
  148. pptx2/skill/references/three-d.md +109 -0
  149. pptx2/skill/references/transitions.md +100 -0
  150. pptx2/slide.py +1244 -0
  151. pptx2/smart_art.py +220 -0
  152. pptx2/spec.py +633 -0
  153. pptx2/table.py +1181 -0
  154. pptx2/table_styles.py +184 -0
  155. pptx2/templates/default.pptx +0 -0
  156. pptx2/templates/docx-icon.emf +0 -0
  157. pptx2/templates/generic-icon.emf +0 -0
  158. pptx2/templates/notes.xml +23 -0
  159. pptx2/templates/notesMaster.xml +352 -0
  160. pptx2/templates/pptx-icon.emf +0 -0
  161. pptx2/templates/theme.xml +321 -0
  162. pptx2/templates/xlsx-icon.emf +0 -0
  163. pptx2/text/__init__.py +0 -0
  164. pptx2/text/fonts.py +482 -0
  165. pptx2/text/layout.py +374 -0
  166. pptx2/text/text.py +1272 -0
  167. pptx2/theme.py +721 -0
  168. pptx2/types.py +36 -0
  169. pptx2/util.py +263 -0
  170. python_pptx2-2.13.0.dist-info/METADATA +351 -0
  171. python_pptx2-2.13.0.dist-info/RECORD +175 -0
  172. python_pptx2-2.13.0.dist-info/WHEEL +5 -0
  173. python_pptx2-2.13.0.dist-info/entry_points.txt +3 -0
  174. python_pptx2-2.13.0.dist-info/licenses/LICENSE +22 -0
  175. python_pptx2-2.13.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,467 @@
1
+ # pyright: reportPrivateUsage=false
2
+
3
+ """lxml custom element classes for shape-related XML elements."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import TYPE_CHECKING, Callable, cast
8
+
9
+ from pptx2.enum.shapes import MSO_AUTO_SHAPE_TYPE, PP_PLACEHOLDER
10
+ from pptx2.oxml import parse_xml
11
+ from pptx2.oxml.ns import nsdecls
12
+ from pptx2.oxml.shapes.shared import BaseShapeElement
13
+ from pptx2.oxml.simpletypes import (
14
+ ST_Coordinate,
15
+ ST_PathShadeType,
16
+ ST_PositiveCoordinate,
17
+ XsdBoolean,
18
+ XsdString,
19
+ )
20
+ from pptx2.oxml.text import CT_TextBody
21
+ from pptx2.oxml.xmlchemy import (
22
+ BaseOxmlElement,
23
+ OneAndOnlyOne,
24
+ OptionalAttribute,
25
+ RequiredAttribute,
26
+ ZeroOrMore,
27
+ ZeroOrOne,
28
+ )
29
+
30
+ if TYPE_CHECKING:
31
+ from pptx2.oxml.shapes.shared import (
32
+ CT_ApplicationNonVisualDrawingProps,
33
+ CT_NonVisualDrawingProps,
34
+ CT_ShapeProperties,
35
+ )
36
+ from pptx2.util import Length
37
+
38
+
39
+ class CT_AdjPoint2D(BaseOxmlElement):
40
+ """`a:pt` custom element class."""
41
+
42
+ x: Length = RequiredAttribute("x", ST_Coordinate) # pyright: ignore[reportAssignmentType]
43
+ y: Length = RequiredAttribute("y", ST_Coordinate) # pyright: ignore[reportAssignmentType]
44
+
45
+
46
+ class CT_CustomGeometry2D(BaseOxmlElement):
47
+ """`a:custGeom` custom element class."""
48
+
49
+ get_or_add_pathLst: Callable[[], CT_Path2DList]
50
+
51
+ _tag_seq = ("a:avLst", "a:gdLst", "a:ahLst", "a:cxnLst", "a:rect", "a:pathLst")
52
+ pathLst: CT_Path2DList | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
53
+ "a:pathLst", successors=_tag_seq[6:]
54
+ )
55
+
56
+
57
+ class CT_GeomGuide(BaseOxmlElement):
58
+ """`a:gd` custom element class.
59
+
60
+ Defines a "guide", corresponding to a yellow diamond-shaped handle on an autoshape.
61
+ """
62
+
63
+ name: str = RequiredAttribute("name", XsdString) # pyright: ignore[reportAssignmentType]
64
+ fmla: str = RequiredAttribute("fmla", XsdString) # pyright: ignore[reportAssignmentType]
65
+
66
+
67
+ class CT_GeomGuideList(BaseOxmlElement):
68
+ """`a:avLst` custom element class."""
69
+
70
+ _add_gd: Callable[[], CT_GeomGuide]
71
+
72
+ gd_lst: list[CT_GeomGuide]
73
+
74
+ gd = ZeroOrMore("a:gd")
75
+
76
+
77
+ class CT_NonVisualDrawingShapeProps(BaseShapeElement):
78
+ """`p:cNvSpPr` custom element class."""
79
+
80
+ spLocks = ZeroOrOne("a:spLocks")
81
+ txBox: bool | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
82
+ "txBox", XsdBoolean
83
+ )
84
+
85
+
86
+ class CT_Path2D(BaseOxmlElement):
87
+ """`a:path` custom element class.
88
+
89
+ Used both as a 2D drawing path child of `a:pathLst` (geometry) and as the
90
+ non-linear shade-property child of `a:gradFill`. The gradient-only
91
+ `path` attribute (``"circle" | "rect" | "shape"``) is exposed alongside
92
+ the geometry-only `w`/`h` attributes — neither overlaps in valid OOXML.
93
+ """
94
+
95
+ _add_close: Callable[[], CT_Path2DClose]
96
+ _add_lnTo: Callable[[], CT_Path2DLineTo]
97
+ _add_moveTo: Callable[[], CT_Path2DMoveTo]
98
+
99
+ close = ZeroOrMore("a:close", successors=())
100
+ lnTo = ZeroOrMore("a:lnTo", successors=())
101
+ moveTo = ZeroOrMore("a:moveTo", successors=())
102
+ w: Length | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
103
+ "w", ST_PositiveCoordinate
104
+ )
105
+ h: Length | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
106
+ "h", ST_PositiveCoordinate
107
+ )
108
+ path: str | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
109
+ "path", ST_PathShadeType
110
+ )
111
+
112
+ def add_close(self) -> CT_Path2DClose:
113
+ """Return a newly created `a:close` element.
114
+
115
+ The new `a:close` element is appended to this `a:path` element.
116
+ """
117
+ return self._add_close()
118
+
119
+ def add_lnTo(self, x: Length, y: Length) -> CT_Path2DLineTo:
120
+ """Return a newly created `a:lnTo` subtree with end point *(x, y)*.
121
+
122
+ The new `a:lnTo` element is appended to this `a:path` element.
123
+ """
124
+ lnTo = self._add_lnTo()
125
+ pt = lnTo._add_pt()
126
+ pt.x, pt.y = x, y
127
+ return lnTo
128
+
129
+ def add_moveTo(self, x: Length, y: Length):
130
+ """Return a newly created `a:moveTo` subtree with point `(x, y)`.
131
+
132
+ The new `a:moveTo` element is appended to this `a:path` element.
133
+ """
134
+ moveTo = self._add_moveTo()
135
+ pt = moveTo._add_pt()
136
+ pt.x, pt.y = x, y
137
+ return moveTo
138
+
139
+
140
+ class CT_Path2DClose(BaseOxmlElement):
141
+ """`a:close` custom element class."""
142
+
143
+
144
+ class CT_Path2DLineTo(BaseOxmlElement):
145
+ """`a:lnTo` custom element class."""
146
+
147
+ _add_pt: Callable[[], CT_AdjPoint2D]
148
+
149
+ pt = ZeroOrOne("a:pt", successors=())
150
+
151
+
152
+ class CT_Path2DList(BaseOxmlElement):
153
+ """`a:pathLst` custom element class."""
154
+
155
+ _add_path: Callable[[], CT_Path2D]
156
+
157
+ path = ZeroOrMore("a:path", successors=())
158
+
159
+ def add_path(self, w: Length, h: Length):
160
+ """Return a newly created `a:path` child element."""
161
+ path = self._add_path()
162
+ path.w, path.h = w, h
163
+ return path
164
+
165
+
166
+ class CT_Path2DMoveTo(BaseOxmlElement):
167
+ """`a:moveTo` custom element class."""
168
+
169
+ _add_pt: Callable[[], CT_AdjPoint2D]
170
+
171
+ pt = ZeroOrOne("a:pt", successors=())
172
+
173
+
174
+ class CT_PresetGeometry2D(BaseOxmlElement):
175
+ """`a:prstGeom` custom element class."""
176
+
177
+ _add_avLst: Callable[[], CT_GeomGuideList]
178
+ _remove_avLst: Callable[[], None]
179
+
180
+ avLst: CT_GeomGuideList | None = ZeroOrOne("a:avLst") # pyright: ignore[reportAssignmentType]
181
+ prst: MSO_AUTO_SHAPE_TYPE = RequiredAttribute( # pyright: ignore[reportAssignmentType]
182
+ "prst", MSO_AUTO_SHAPE_TYPE
183
+ )
184
+
185
+ @property
186
+ def gd_lst(self) -> list[CT_GeomGuide]:
187
+ """Sequence of `a:gd` element children of `a:avLst`. Empty if none are present."""
188
+ avLst = self.avLst
189
+ if avLst is None:
190
+ return []
191
+ return avLst.gd_lst
192
+
193
+ def rewrite_guides(self, guides: list[tuple[str, int]]):
194
+ """Replace any `a:gd` element children of `a:avLst` with ones forme from `guides`."""
195
+ self._remove_avLst()
196
+ avLst = self._add_avLst()
197
+ for name, val in guides:
198
+ gd = avLst._add_gd()
199
+ gd.name = name
200
+ gd.fmla = "val %d" % val
201
+
202
+
203
+ class CT_Shape(BaseShapeElement):
204
+ """`p:sp` custom element class."""
205
+
206
+ get_or_add_txBody: Callable[[], CT_TextBody]
207
+
208
+ nvSpPr: CT_ShapeNonVisual = OneAndOnlyOne("p:nvSpPr") # pyright: ignore[reportAssignmentType]
209
+ spPr: CT_ShapeProperties = OneAndOnlyOne("p:spPr") # pyright: ignore[reportAssignmentType]
210
+ txBody: CT_TextBody | None = ZeroOrOne("p:txBody", successors=("p:extLst",)) # pyright: ignore
211
+
212
+ def add_path(self, w: Length, h: Length) -> CT_Path2D:
213
+ custGeom = self.spPr.custGeom
214
+ if custGeom is None:
215
+ raise ValueError("shape must be freeform")
216
+ pathLst = custGeom.get_or_add_pathLst()
217
+ return pathLst.add_path(w=w, h=h)
218
+
219
+ def get_or_add_ln(self):
220
+ """Return the `a:ln` grandchild element, newly added if not present."""
221
+ return self.spPr.get_or_add_ln()
222
+
223
+ @property
224
+ def has_custom_geometry(self):
225
+ """True if this shape has custom geometry, i.e. is a freeform shape.
226
+
227
+ A shape has custom geometry if it has a `p:spPr/a:custGeom`
228
+ descendant (instead of `p:spPr/a:prstGeom`).
229
+ """
230
+ return self.spPr.custGeom is not None
231
+
232
+ @property
233
+ def is_autoshape(self):
234
+ """True if this shape is an auto shape.
235
+
236
+ A shape is an auto shape if it has a `a:prstGeom` element and does not have a txBox="1"
237
+ attribute on cNvSpPr.
238
+ """
239
+ prstGeom = self.prstGeom
240
+ if prstGeom is None:
241
+ return False
242
+ return self.nvSpPr.cNvSpPr.txBox is not True
243
+
244
+ @property
245
+ def is_textbox(self):
246
+ """True if this shape is a text box.
247
+
248
+ A shape is a text box if it has a `txBox` attribute on cNvSpPr that resolves to |True|.
249
+ The default when the txBox attribute is missing is |False|.
250
+ """
251
+ return self.nvSpPr.cNvSpPr.txBox is True
252
+
253
+ @property
254
+ def ln(self):
255
+ """`a:ln` grand-child element or |None| if not present."""
256
+ return self.spPr.ln
257
+
258
+ @staticmethod
259
+ def new_autoshape_sp(
260
+ id_: int, name: str, prst: str, left: int, top: int, width: int, height: int
261
+ ) -> CT_Shape:
262
+ """Return a new `p:sp` element tree configured as a base auto shape."""
263
+ xml = (
264
+ "<p:sp %s>\n"
265
+ " <p:nvSpPr>\n"
266
+ ' <p:cNvPr id="%s" name="%s"/>\n'
267
+ " <p:cNvSpPr/>\n"
268
+ " <p:nvPr/>\n"
269
+ " </p:nvSpPr>\n"
270
+ " <p:spPr>\n"
271
+ " <a:xfrm>\n"
272
+ ' <a:off x="%s" y="%s"/>\n'
273
+ ' <a:ext cx="%s" cy="%s"/>\n'
274
+ " </a:xfrm>\n"
275
+ ' <a:prstGeom prst="%s">\n'
276
+ " <a:avLst/>\n"
277
+ " </a:prstGeom>\n"
278
+ " </p:spPr>\n"
279
+ " <p:style>\n"
280
+ ' <a:lnRef idx="1">\n'
281
+ ' <a:schemeClr val="accent1"/>\n'
282
+ " </a:lnRef>\n"
283
+ ' <a:fillRef idx="3">\n'
284
+ ' <a:schemeClr val="accent1"/>\n'
285
+ " </a:fillRef>\n"
286
+ ' <a:effectRef idx="2">\n'
287
+ ' <a:schemeClr val="accent1"/>\n'
288
+ " </a:effectRef>\n"
289
+ ' <a:fontRef idx="minor">\n'
290
+ ' <a:schemeClr val="lt1"/>\n'
291
+ " </a:fontRef>\n"
292
+ " </p:style>\n"
293
+ " <p:txBody>\n"
294
+ ' <a:bodyPr rtlCol="0" anchor="ctr"/>\n'
295
+ " <a:lstStyle/>\n"
296
+ " <a:p>\n"
297
+ ' <a:pPr algn="ctr"/>\n'
298
+ ' <a:endParaRPr lang="en-US"/>\n'
299
+ " </a:p>\n"
300
+ " </p:txBody>\n"
301
+ "</p:sp>" % (nsdecls("a", "p"), "%d", "%s", "%d", "%d", "%d", "%d", "%s")
302
+ ) % (id_, name, left, top, width, height, prst)
303
+ return cast(CT_Shape, parse_xml(xml))
304
+
305
+ @staticmethod
306
+ def new_freeform_sp(shape_id: int, name: str, x: int, y: int, cx: int, cy: int):
307
+ """Return new `p:sp` element tree configured as freeform shape.
308
+
309
+ The returned shape has a `a:custGeom` subtree but no paths in its
310
+ path list.
311
+ """
312
+ xml = (
313
+ "<p:sp %s>\n"
314
+ " <p:nvSpPr>\n"
315
+ ' <p:cNvPr id="%s" name="%s"/>\n'
316
+ " <p:cNvSpPr/>\n"
317
+ " <p:nvPr/>\n"
318
+ " </p:nvSpPr>\n"
319
+ " <p:spPr>\n"
320
+ " <a:xfrm>\n"
321
+ ' <a:off x="%s" y="%s"/>\n'
322
+ ' <a:ext cx="%s" cy="%s"/>\n'
323
+ " </a:xfrm>\n"
324
+ " <a:custGeom>\n"
325
+ " <a:avLst/>\n"
326
+ " <a:gdLst/>\n"
327
+ " <a:ahLst/>\n"
328
+ " <a:cxnLst/>\n"
329
+ ' <a:rect l="l" t="t" r="r" b="b"/>\n'
330
+ " <a:pathLst/>\n"
331
+ " </a:custGeom>\n"
332
+ " </p:spPr>\n"
333
+ " <p:style>\n"
334
+ ' <a:lnRef idx="1">\n'
335
+ ' <a:schemeClr val="accent1"/>\n'
336
+ " </a:lnRef>\n"
337
+ ' <a:fillRef idx="3">\n'
338
+ ' <a:schemeClr val="accent1"/>\n'
339
+ " </a:fillRef>\n"
340
+ ' <a:effectRef idx="2">\n'
341
+ ' <a:schemeClr val="accent1"/>\n'
342
+ " </a:effectRef>\n"
343
+ ' <a:fontRef idx="minor">\n'
344
+ ' <a:schemeClr val="lt1"/>\n'
345
+ " </a:fontRef>\n"
346
+ " </p:style>\n"
347
+ " <p:txBody>\n"
348
+ ' <a:bodyPr rtlCol="0" anchor="ctr"/>\n'
349
+ " <a:lstStyle/>\n"
350
+ " <a:p>\n"
351
+ ' <a:pPr algn="ctr"/>\n'
352
+ ' <a:endParaRPr lang="en-US"/>\n'
353
+ " </a:p>\n"
354
+ " </p:txBody>\n"
355
+ "</p:sp>" % (nsdecls("a", "p"), "%d", "%s", "%d", "%d", "%d", "%d")
356
+ ) % (shape_id, name, x, y, cx, cy)
357
+ return cast(CT_Shape, parse_xml(xml))
358
+
359
+ @staticmethod
360
+ def new_placeholder_sp(
361
+ id_: int, name: str, ph_type: PP_PLACEHOLDER, orient: str, sz, idx
362
+ ) -> CT_Shape:
363
+ """Return a new `p:sp` element tree configured as a placeholder shape."""
364
+ sp = cast(
365
+ CT_Shape,
366
+ parse_xml(
367
+ f"<p:sp {nsdecls('a', 'p')}>\n"
368
+ f" <p:nvSpPr>\n"
369
+ f' <p:cNvPr id="{id_}" name="{name}"/>\n'
370
+ f" <p:cNvSpPr>\n"
371
+ f' <a:spLocks noGrp="1"/>\n'
372
+ f" </p:cNvSpPr>\n"
373
+ f" <p:nvPr/>\n"
374
+ f" </p:nvSpPr>\n"
375
+ f" <p:spPr/>\n"
376
+ f"</p:sp>"
377
+ ),
378
+ )
379
+
380
+ ph = sp.nvSpPr.nvPr.get_or_add_ph()
381
+ ph.type = ph_type
382
+ ph.idx = idx
383
+ ph.orient = orient
384
+ ph.sz = sz
385
+
386
+ placeholder_types_that_have_a_text_frame = (
387
+ PP_PLACEHOLDER.TITLE,
388
+ PP_PLACEHOLDER.CENTER_TITLE,
389
+ PP_PLACEHOLDER.SUBTITLE,
390
+ PP_PLACEHOLDER.BODY,
391
+ PP_PLACEHOLDER.OBJECT,
392
+ )
393
+
394
+ if ph_type in placeholder_types_that_have_a_text_frame:
395
+ sp.append(CT_TextBody.new())
396
+
397
+ return sp
398
+
399
+ @staticmethod
400
+ def new_textbox_sp(id_, name, left, top, width, height):
401
+ """Return a new `p:sp` element tree configured as a base textbox shape."""
402
+ tmpl = CT_Shape._textbox_sp_tmpl()
403
+ xml = tmpl % (id_, name, left, top, width, height)
404
+ sp = parse_xml(xml)
405
+ return sp
406
+
407
+ @property
408
+ def prst(self):
409
+ """Value of `prst` attribute of `a:prstGeom` element or |None| if not present."""
410
+ prstGeom = self.prstGeom
411
+ if prstGeom is None:
412
+ return None
413
+ return prstGeom.prst
414
+
415
+ @property
416
+ def prstGeom(self) -> CT_PresetGeometry2D:
417
+ """Reference to `a:prstGeom` child element.
418
+
419
+ |None| if this shape doesn't have one, for example, if it's a placeholder shape.
420
+ """
421
+ return self.spPr.prstGeom
422
+
423
+ def _new_txBody(self):
424
+ return CT_TextBody.new_p_txBody()
425
+
426
+ @staticmethod
427
+ def _textbox_sp_tmpl():
428
+ return (
429
+ "<p:sp %s>\n"
430
+ " <p:nvSpPr>\n"
431
+ ' <p:cNvPr id="%s" name="%s"/>\n'
432
+ ' <p:cNvSpPr txBox="1"/>\n'
433
+ " <p:nvPr/>\n"
434
+ " </p:nvSpPr>\n"
435
+ " <p:spPr>\n"
436
+ " <a:xfrm>\n"
437
+ ' <a:off x="%s" y="%s"/>\n'
438
+ ' <a:ext cx="%s" cy="%s"/>\n'
439
+ " </a:xfrm>\n"
440
+ ' <a:prstGeom prst="rect">\n'
441
+ " <a:avLst/>\n"
442
+ " </a:prstGeom>\n"
443
+ " <a:noFill/>\n"
444
+ " </p:spPr>\n"
445
+ " <p:txBody>\n"
446
+ ' <a:bodyPr wrap="none">\n'
447
+ " <a:spAutoFit/>\n"
448
+ " </a:bodyPr>\n"
449
+ " <a:lstStyle/>\n"
450
+ " <a:p/>\n"
451
+ " </p:txBody>\n"
452
+ "</p:sp>" % (nsdecls("a", "p"), "%d", "%s", "%d", "%d", "%d", "%d")
453
+ )
454
+
455
+
456
+ class CT_ShapeNonVisual(BaseShapeElement):
457
+ """`p:nvSpPr` custom element class."""
458
+
459
+ cNvPr: CT_NonVisualDrawingProps = OneAndOnlyOne( # pyright: ignore[reportAssignmentType]
460
+ "p:cNvPr"
461
+ )
462
+ cNvSpPr: CT_NonVisualDrawingShapeProps = OneAndOnlyOne( # pyright: ignore[reportAssignmentType]
463
+ "p:cNvSpPr"
464
+ )
465
+ nvPr: CT_ApplicationNonVisualDrawingProps = ( # pyright: ignore[reportAssignmentType]
466
+ OneAndOnlyOne("p:nvPr")
467
+ )
@@ -0,0 +1,107 @@
1
+ """lxml custom element classes for XML elements related to the Connector shape."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, cast
6
+
7
+ from pptx2.oxml import parse_xml
8
+ from pptx2.oxml.ns import nsdecls
9
+ from pptx2.oxml.shapes.shared import BaseShapeElement
10
+ from pptx2.oxml.simpletypes import ST_DrawingElementId, XsdUnsignedInt
11
+ from pptx2.oxml.xmlchemy import BaseOxmlElement, OneAndOnlyOne, RequiredAttribute, ZeroOrOne
12
+
13
+ if TYPE_CHECKING:
14
+ from pptx2.oxml.shapes.shared import CT_ShapeProperties
15
+
16
+
17
+ class CT_Connection(BaseShapeElement):
18
+ """A `a:stCxn` or `a:endCxn` element.
19
+
20
+ Specifies a connection between an end-point of a connector and a shape connection point.
21
+ """
22
+
23
+ id = RequiredAttribute("id", ST_DrawingElementId)
24
+ idx = RequiredAttribute("idx", XsdUnsignedInt)
25
+
26
+
27
+ class CT_Connector(BaseShapeElement):
28
+ """A line/connector shape `p:cxnSp` element"""
29
+
30
+ _tag_seq = ("p:nvCxnSpPr", "p:spPr", "p:style", "p:extLst")
31
+ nvCxnSpPr = OneAndOnlyOne("p:nvCxnSpPr")
32
+ spPr: CT_ShapeProperties = OneAndOnlyOne("p:spPr") # pyright: ignore[reportAssignmentType]
33
+ del _tag_seq
34
+
35
+ @classmethod
36
+ def new_cxnSp(
37
+ cls,
38
+ id_: int,
39
+ name: str,
40
+ prst: str,
41
+ x: int,
42
+ y: int,
43
+ cx: int,
44
+ cy: int,
45
+ flipH: bool,
46
+ flipV: bool,
47
+ ) -> CT_Connector:
48
+ """Return a new `p:cxnSp` element tree configured as a base connector."""
49
+ flip = (' flipH="1"' if flipH else "") + (' flipV="1"' if flipV else "")
50
+ return cast(
51
+ CT_Connector,
52
+ parse_xml(
53
+ f"<p:cxnSp {nsdecls('a', 'p')}>\n"
54
+ f" <p:nvCxnSpPr>\n"
55
+ f' <p:cNvPr id="{id_}" name="{name}"/>\n'
56
+ f" <p:cNvCxnSpPr/>\n"
57
+ f" <p:nvPr/>\n"
58
+ f" </p:nvCxnSpPr>\n"
59
+ f" <p:spPr>\n"
60
+ f" <a:xfrm{flip}>\n"
61
+ f' <a:off x="{x}" y="{y}"/>\n'
62
+ f' <a:ext cx="{cx}" cy="{cy}"/>\n'
63
+ f" </a:xfrm>\n"
64
+ f' <a:prstGeom prst="{prst}">\n'
65
+ f" <a:avLst/>\n"
66
+ f" </a:prstGeom>\n"
67
+ f" </p:spPr>\n"
68
+ f" <p:style>\n"
69
+ f' <a:lnRef idx="2">\n'
70
+ f' <a:schemeClr val="accent1"/>\n'
71
+ f" </a:lnRef>\n"
72
+ f' <a:fillRef idx="0">\n'
73
+ f' <a:schemeClr val="accent1"/>\n'
74
+ f" </a:fillRef>\n"
75
+ f' <a:effectRef idx="1">\n'
76
+ f' <a:schemeClr val="accent1"/>\n'
77
+ f" </a:effectRef>\n"
78
+ f' <a:fontRef idx="minor">\n'
79
+ f' <a:schemeClr val="tx1"/>\n'
80
+ f" </a:fontRef>\n"
81
+ f" </p:style>\n"
82
+ f"</p:cxnSp>"
83
+ ),
84
+ )
85
+
86
+
87
+ class CT_ConnectorNonVisual(BaseOxmlElement):
88
+ """
89
+ `p:nvCxnSpPr` element, container for the non-visual properties of
90
+ a connector, such as name, id, etc.
91
+ """
92
+
93
+ cNvPr = OneAndOnlyOne("p:cNvPr")
94
+ cNvCxnSpPr = OneAndOnlyOne("p:cNvCxnSpPr")
95
+ nvPr = OneAndOnlyOne("p:nvPr")
96
+
97
+
98
+ class CT_NonVisualConnectorProperties(BaseOxmlElement):
99
+ """
100
+ `p:cNvCxnSpPr` element, container for the non-visual properties specific
101
+ to a connector shape, such as connections and connector locking.
102
+ """
103
+
104
+ _tag_seq = ("a:cxnSpLocks", "a:stCxn", "a:endCxn", "a:extLst")
105
+ stCxn = ZeroOrOne("a:stCxn", successors=_tag_seq[2:])
106
+ endCxn = ZeroOrOne("a:endCxn", successors=_tag_seq[3:])
107
+ del _tag_seq