Skip to content

Commit ca07d11

Browse files
committed
text: added CT_jc and CT_textDirection
added CT_jc and CT_textDirection functions and got them working.
1 parent cca918b commit ca07d11

4 files changed

Lines changed: 270 additions & 4 deletions

File tree

docx/oxml/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# custom element class mappings
1313
# ===========================================================================
1414

15-
from docx.oxml.shared import CT_DecimalNumber, CT_OnOff, CT_String, CT_Shading
15+
from docx.oxml.shared import CT_DecimalNumber, CT_OnOff, CT_String, CT_Shd
1616

1717
from docx.oxml.shape import (
1818
CT_Blip, CT_BlipFillProperties, CT_GraphicalObject,
@@ -54,7 +54,7 @@
5454
register_custom_element_class('w:tr', CT_Row)
5555
register_custom_element_class('w:tcPr', CT_TcPr)
5656
register_custom_element_class('w:gridSpan', CT_DecimalNumber)
57-
register_custom_element_class('w:shd', CT_Shading)
57+
register_custom_element_class('w:shd', CT_Shd)
5858

5959
from docx.oxml.text import CT_Br, CT_P, CT_PPr, CT_R, CT_RPr, CT_Text
6060
register_custom_element_class('w:b', CT_OnOff)

docx/oxml/shared.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,115 @@ def val(self):
341341
def val(self, val):
342342
return self.set(qn('w:val'), val)
343343

344+
class CT_Ind(OxmlBaseElement):
345+
@classmethod
346+
def new(cls, nsptagname, valDict):
347+
"""
348+
Return a new ``CT_Ind`` element with tagname *nsptagname* and
349+
attributes set by key, value pairs in *valDict*.
350+
"""
351+
attrsDict = {}
352+
for k, v in valDict.iteritems():
353+
attrsDict[qn('w:'+str(k))] = v
354+
return OxmlElement(nsptagname, attrs=attrsDict)
355+
356+
@property
357+
def valDict(self):
358+
valDict={}
359+
for val in ['start','startChars','end','endChars','left','leftChars',
360+
'right','rightChars','hanging','hangingChars','firstLine',
361+
'firstLineChars']:
362+
valDict[val] = self.get(qn('w:'+val))
363+
return valDict
364+
@valDict.setter
365+
def valDict(self, valDict):
366+
for k, v in valDict:
367+
self.set(qn('w:'+str(k)), v)
368+
return
369+
370+
@property
371+
def start(self):
372+
return self.get(qn('w:start'))
373+
@start.setter
374+
def start(self, start):
375+
return self.set(qn('w:start'), start)
376+
377+
@property
378+
def startChars(self):
379+
return self.get(qn('w:startChars'))
380+
@startChars.setter
381+
def startChars(self, startChars):
382+
return self.set(qn('w:startChars'), startChars)
383+
384+
@property
385+
def end(self):
386+
return self.get(qn('w:end'))
387+
@end.setter
388+
def end(self, end):
389+
return self.set(qn('w:end'), end)
390+
391+
@property
392+
def endChars(self):
393+
return self.get(qn('w:endChars'))
394+
@endChars.setter
395+
def endChars(self, endChars):
396+
return self.set(qn('w:endChars'), endChars)
397+
398+
@property
399+
def left(self):
400+
return self.get(qn('w:left'))
401+
@left.setter
402+
def left(self, left):
403+
return self.set(qn('w:left'), left)
404+
405+
@property
406+
def leftChars(self):
407+
return self.get(qn('w:leftChars'))
408+
@leftChars.setter
409+
def leftChars(self, leftChars):
410+
return self.set(qn('w:leftChars'), leftChars)
411+
412+
@property
413+
def right(self):
414+
return self.get(qn('w:right'))
415+
@right.setter
416+
def right(self, right):
417+
return self.set(qn('w:right'), right)
418+
419+
@property
420+
def rightChars(self):
421+
return self.get(qn('w:rightChars'))
422+
@rightChars.setter
423+
def rightChars(self, rightChars):
424+
return self.set(qn('w:rightChars'), rightChars)
425+
426+
@property
427+
def hanging(self):
428+
return self.get(qn('w:hanging'))
429+
@hanging.setter
430+
def hanging(self, hanging):
431+
return self.set(qn('w:hanging'), hanging)
432+
433+
@property
434+
def hangingChars(self):
435+
return self.get(qn('w:hangingChars'))
436+
@hangingChars.setter
437+
def hangingChars(self, hangingChars):
438+
return self.set(qn('w:hangingChars'), hangingChars)
439+
440+
@property
441+
def firstLine(self):
442+
return self.get(qn('w:firstLine'))
443+
@firstLine.setter
444+
def firstLine(self, firstLine):
445+
return self.set(qn('w:firstLine'), firstLine)
446+
447+
@property
448+
def firstLineChars(self):
449+
return self.get(qn('w:firstLineChars'))
450+
@firstLineChars.setter
451+
def firstLineChars(self, firstLineChars):
452+
return self.set(qn('w:firstLineChars'), firstLineChars)
344453

345454
class CT_Shd(OxmlBaseElement):
346455
@classmethod

docx/oxml/text.py

Lines changed: 147 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
from docx.oxml.parts.numbering import CT_NumPr
99
from docx.oxml.shared import (
10-
CT_String, nsdecls, OxmlBaseElement, OxmlElement, oxml_fromstring, qn
10+
CT_String,
11+
nsdecls, OxmlBaseElement, OxmlElement, oxml_fromstring, qn
1112
)
1213
from docx.enum.text import WD_UNDERLINE
1314

@@ -102,6 +103,46 @@ def style(self, style):
102103
"""
103104
pPr = self.get_or_add_pPr()
104105
pPr.style = style
106+
107+
@property
108+
def jc(self):
109+
"""
110+
String contained in w:val attribute of <w:pPr><w:jc> child, or
111+
None if that element is not present.
112+
"""
113+
pPr = self.pPr
114+
if pPr is None:
115+
return None
116+
return pPr.jc
117+
118+
@jc.setter
119+
def jc(self, jc):
120+
"""
121+
Set style of this <w:p> element to *jc*. If *jc* is None,
122+
remove the style element.
123+
"""
124+
pPr = self.get_or_add_pPr()
125+
pPr.jc = jc
126+
127+
@property
128+
def textDirection(self):
129+
"""
130+
String contained in w:val attribute of <w:pPr><w:textDirection> child,
131+
or None if that element is not present.
132+
"""
133+
pPr = self.pPr
134+
if pPr is None:
135+
return None
136+
return pPr.textdirection
137+
138+
@textDirection.setter
139+
def textDirection(self, textdirection):
140+
"""
141+
Set style of this <w:p> element to *style*. If *style* is None,
142+
remove the style element.
143+
"""
144+
pPr = self.get_or_add_pPr()
145+
pPr.textdirection = textdirection
105146

106147
def _add_pPr(self):
107148
"""
@@ -133,6 +174,15 @@ def get_or_add_pStyle(self):
133174
if pStyle is None:
134175
pStyle = self._add_pStyle()
135176
return pStyle
177+
178+
def get_or_add_textDirectionElement(self):
179+
"""
180+
Return the textDirection child element, newly added if not present.
181+
"""
182+
textDirection = self.textDirection
183+
if textDirection is None:
184+
textDirection = self._add_textDirection()
185+
return textDirection
136186

137187
@staticmethod
138188
def new():
@@ -186,6 +236,80 @@ def style(self, style):
186236
self._add_pStyle(style)
187237
else:
188238
self.pStyle.val = style
239+
240+
@property
241+
def jcElement(self):
242+
"""
243+
``<w:jc>`` child element or None if not present.
244+
"""
245+
return self.find(qn('w:jc'))
246+
247+
def remove_jcElement(self):
248+
jcElement = self.jcElement
249+
if jcElement is not None:
250+
self.remove(jcElement)
251+
252+
@property
253+
def jc(self):
254+
"""
255+
String contained in <w:jc> child, or None if that element is
256+
not present.
257+
"""
258+
jc = self.jcElement
259+
if jc is None:
260+
return None
261+
return jc.get(qn('w:val'))
262+
263+
@jc.setter
264+
def jc(self, jc):
265+
"""
266+
Set val attribute of <w:jc> child element to *jc*, adding a
267+
new element if necessary. If *jc* is |None|, remove the <w:jc>
268+
element if present.
269+
"""
270+
if jc is None:
271+
self.remove_jcDirection()
272+
elif self.jcElement is None:
273+
self._add_jcElement(jc)
274+
else:
275+
self.jcElement.val = jc
276+
277+
@property
278+
def textDirectionElement(self):
279+
"""
280+
``<w:pStyle>`` child element or None if not present.
281+
"""
282+
return self.find(qn('w:textDirection'))
283+
284+
def remove_textDirectionElement(self):
285+
textDirectionElement = self.textDirectionElement
286+
if textDirectionElement is not None:
287+
self.remove(textDirectionElement)
288+
289+
@property
290+
def textDirection(self):
291+
"""
292+
String contained in <w:textDirection> child, or None if that element is
293+
not present.
294+
"""
295+
textDirection = self.textDirectionElement
296+
if textDirection is None:
297+
return None
298+
return textDirection.get(qn('w:val'))
299+
300+
@textDirection.setter
301+
def textDirection(self, textDirection):
302+
"""
303+
Set val attribute of <w:textDirection> child element to
304+
*textDirection*, adding a new element if necessary. If *textDirection*
305+
is |None|, remove the <w:textDirection> element if present.
306+
"""
307+
if textDirection is None:
308+
self.remove_textDirectionElement()
309+
elif self.textDirectionElement is None:
310+
self._add_textDirectionElement(textDirection)
311+
else:
312+
self.textDirectionElement.val = textDirection
189313

190314
def _add_numPr(self):
191315
numPr = CT_NumPr.new()
@@ -194,6 +318,14 @@ def _add_numPr(self):
194318
def _add_pStyle(self, style):
195319
pStyle = CT_String.new_pStyle(style)
196320
return self._insert_pStyle(pStyle)
321+
322+
def _add_jcElement(self, jc):
323+
jcElement = CT_String.new('w:jc', jc)
324+
return self._insert_jcElement(jcElement)
325+
326+
def _add_textDirectionElement(self, textDirection):
327+
textDirectionElement = CT_String.new('w:textDirection', textDirection)
328+
return self._insert_textDirectionElement(textDirectionElement)
197329

198330
def _insert_numPr(self, numPr):
199331
return self.insert_element_before(
@@ -210,7 +342,20 @@ def _insert_numPr(self, numPr):
210342
def _insert_pStyle(self, pStyle):
211343
self.insert(0, pStyle)
212344
return pStyle
213-
345+
346+
def _insert_jcElement(self, jc):
347+
return self.insert_element_before(
348+
jc, 'w:textDirection', 'w:textAlignment', 'w:textboxTightWrap',
349+
'w:outlineLvl', 'w:divId', 'w:cnfStyle', 'w:rPr', 'w:sectPr',
350+
'w:pPrChange'
351+
)
352+
353+
def _insert_textDirectionElement(self, textDirection):
354+
return self.insert_element_before(
355+
textDirection, 'w:textAlignment', 'w:textboxTightWrap',
356+
'w:outlineLvl', 'w:divId', 'w:cnfStyle', 'w:rPr', 'w:sectPr',
357+
'w:pPrChange'
358+
)
214359

215360
class CT_R(OxmlBaseElement):
216361
"""

docx/text.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,18 @@ def style(self):
8787
@style.setter
8888
def style(self, style):
8989
self._p.style = None if style == 'Normal' else style
90+
91+
@property
92+
def jc(self):
93+
"""
94+
Justification for this paragraph. Read/Write.
95+
"""
96+
jc = self._p.jc
97+
return jc if jc is not None else 'start'
98+
99+
@jc.setter
100+
def jc(self, jc):
101+
self._p.jc = jc
90102

91103
@property
92104
def text(self):

0 commit comments

Comments
 (0)