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