You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
349 lines
10 KiB
349 lines
10 KiB
# encoding: utf-8
|
|
|
|
"""
|
|
Custom element classes related to paragraph properties (CT_PPr).
|
|
"""
|
|
|
|
from ...enum.text import (
|
|
WD_ALIGN_PARAGRAPH, WD_LINE_SPACING, WD_TAB_ALIGNMENT, WD_TAB_LEADER
|
|
)
|
|
from ...shared import Length
|
|
from ..simpletypes import ST_SignedTwipsMeasure, ST_TwipsMeasure
|
|
from ..xmlchemy import (
|
|
BaseOxmlElement, OneOrMore, OptionalAttribute, RequiredAttribute,
|
|
ZeroOrOne
|
|
)
|
|
|
|
|
|
class CT_Ind(BaseOxmlElement):
|
|
"""
|
|
``<w:ind>`` element, specifying paragraph indentation.
|
|
"""
|
|
left = OptionalAttribute('w:left', ST_SignedTwipsMeasure)
|
|
right = OptionalAttribute('w:right', ST_SignedTwipsMeasure)
|
|
firstLine = OptionalAttribute('w:firstLine', ST_TwipsMeasure)
|
|
hanging = OptionalAttribute('w:hanging', ST_TwipsMeasure)
|
|
|
|
|
|
class CT_Jc(BaseOxmlElement):
|
|
"""
|
|
``<w:jc>`` element, specifying paragraph justification.
|
|
"""
|
|
val = RequiredAttribute('w:val', WD_ALIGN_PARAGRAPH)
|
|
|
|
|
|
class CT_PPr(BaseOxmlElement):
|
|
"""
|
|
``<w:pPr>`` element, containing the properties for a paragraph.
|
|
"""
|
|
_tag_seq = (
|
|
'w:pStyle', 'w:keepNext', 'w:keepLines', 'w:pageBreakBefore',
|
|
'w:framePr', 'w:widowControl', 'w:numPr', 'w:suppressLineNumbers',
|
|
'w:pBdr', 'w:shd', 'w:tabs', 'w:suppressAutoHyphens', 'w:kinsoku',
|
|
'w:wordWrap', 'w:overflowPunct', 'w:topLinePunct', 'w:autoSpaceDE',
|
|
'w:autoSpaceDN', 'w:bidi', 'w:adjustRightInd', 'w:snapToGrid',
|
|
'w:spacing', 'w:ind', 'w:contextualSpacing', 'w:mirrorIndents',
|
|
'w:suppressOverlap', 'w:jc', 'w:textDirection', 'w:textAlignment',
|
|
'w:textboxTightWrap', 'w:outlineLvl', 'w:divId', 'w:cnfStyle',
|
|
'w:rPr', 'w:sectPr', 'w:pPrChange'
|
|
)
|
|
pStyle = ZeroOrOne('w:pStyle', successors=_tag_seq[1:])
|
|
keepNext = ZeroOrOne('w:keepNext', successors=_tag_seq[2:])
|
|
keepLines = ZeroOrOne('w:keepLines', successors=_tag_seq[3:])
|
|
pageBreakBefore = ZeroOrOne('w:pageBreakBefore', successors=_tag_seq[4:])
|
|
widowControl = ZeroOrOne('w:widowControl', successors=_tag_seq[6:])
|
|
numPr = ZeroOrOne('w:numPr', successors=_tag_seq[7:])
|
|
tabs = ZeroOrOne('w:tabs', successors=_tag_seq[11:])
|
|
spacing = ZeroOrOne('w:spacing', successors=_tag_seq[22:])
|
|
ind = ZeroOrOne('w:ind', successors=_tag_seq[23:])
|
|
jc = ZeroOrOne('w:jc', successors=_tag_seq[27:])
|
|
sectPr = ZeroOrOne('w:sectPr', successors=_tag_seq[35:])
|
|
del _tag_seq
|
|
|
|
@property
|
|
def first_line_indent(self):
|
|
"""
|
|
A |Length| value calculated from the values of `w:ind/@w:firstLine`
|
|
and `w:ind/@w:hanging`. Returns |None| if the `w:ind` child is not
|
|
present.
|
|
"""
|
|
ind = self.ind
|
|
if ind is None:
|
|
return None
|
|
hanging = ind.hanging
|
|
if hanging is not None:
|
|
return Length(-hanging)
|
|
firstLine = ind.firstLine
|
|
if firstLine is None:
|
|
return None
|
|
return firstLine
|
|
|
|
@first_line_indent.setter
|
|
def first_line_indent(self, value):
|
|
if self.ind is None and value is None:
|
|
return
|
|
ind = self.get_or_add_ind()
|
|
ind.firstLine = ind.hanging = None
|
|
if value is None:
|
|
return
|
|
elif value < 0:
|
|
ind.hanging = -value
|
|
else:
|
|
ind.firstLine = value
|
|
|
|
@property
|
|
def ind_left(self):
|
|
"""
|
|
The value of `w:ind/@w:left` or |None| if not present.
|
|
"""
|
|
ind = self.ind
|
|
if ind is None:
|
|
return None
|
|
return ind.left
|
|
|
|
@ind_left.setter
|
|
def ind_left(self, value):
|
|
if value is None and self.ind is None:
|
|
return
|
|
ind = self.get_or_add_ind()
|
|
ind.left = value
|
|
|
|
@property
|
|
def ind_right(self):
|
|
"""
|
|
The value of `w:ind/@w:right` or |None| if not present.
|
|
"""
|
|
ind = self.ind
|
|
if ind is None:
|
|
return None
|
|
return ind.right
|
|
|
|
@ind_right.setter
|
|
def ind_right(self, value):
|
|
if value is None and self.ind is None:
|
|
return
|
|
ind = self.get_or_add_ind()
|
|
ind.right = value
|
|
|
|
@property
|
|
def jc_val(self):
|
|
"""
|
|
The value of the ``<w:jc>`` child element or |None| if not present.
|
|
"""
|
|
jc = self.jc
|
|
if jc is None:
|
|
return None
|
|
return jc.val
|
|
|
|
@jc_val.setter
|
|
def jc_val(self, value):
|
|
if value is None:
|
|
self._remove_jc()
|
|
return
|
|
self.get_or_add_jc().val = value
|
|
|
|
@property
|
|
def keepLines_val(self):
|
|
"""
|
|
The value of `keepLines/@val` or |None| if not present.
|
|
"""
|
|
keepLines = self.keepLines
|
|
if keepLines is None:
|
|
return None
|
|
return keepLines.val
|
|
|
|
@keepLines_val.setter
|
|
def keepLines_val(self, value):
|
|
if value is None:
|
|
self._remove_keepLines()
|
|
else:
|
|
self.get_or_add_keepLines().val = value
|
|
|
|
@property
|
|
def keepNext_val(self):
|
|
"""
|
|
The value of `keepNext/@val` or |None| if not present.
|
|
"""
|
|
keepNext = self.keepNext
|
|
if keepNext is None:
|
|
return None
|
|
return keepNext.val
|
|
|
|
@keepNext_val.setter
|
|
def keepNext_val(self, value):
|
|
if value is None:
|
|
self._remove_keepNext()
|
|
else:
|
|
self.get_or_add_keepNext().val = value
|
|
|
|
@property
|
|
def pageBreakBefore_val(self):
|
|
"""
|
|
The value of `pageBreakBefore/@val` or |None| if not present.
|
|
"""
|
|
pageBreakBefore = self.pageBreakBefore
|
|
if pageBreakBefore is None:
|
|
return None
|
|
return pageBreakBefore.val
|
|
|
|
@pageBreakBefore_val.setter
|
|
def pageBreakBefore_val(self, value):
|
|
if value is None:
|
|
self._remove_pageBreakBefore()
|
|
else:
|
|
self.get_or_add_pageBreakBefore().val = value
|
|
|
|
@property
|
|
def spacing_after(self):
|
|
"""
|
|
The value of `w:spacing/@w:after` or |None| if not present.
|
|
"""
|
|
spacing = self.spacing
|
|
if spacing is None:
|
|
return None
|
|
return spacing.after
|
|
|
|
@spacing_after.setter
|
|
def spacing_after(self, value):
|
|
if value is None and self.spacing is None:
|
|
return
|
|
self.get_or_add_spacing().after = value
|
|
|
|
@property
|
|
def spacing_before(self):
|
|
"""
|
|
The value of `w:spacing/@w:before` or |None| if not present.
|
|
"""
|
|
spacing = self.spacing
|
|
if spacing is None:
|
|
return None
|
|
return spacing.before
|
|
|
|
@spacing_before.setter
|
|
def spacing_before(self, value):
|
|
if value is None and self.spacing is None:
|
|
return
|
|
self.get_or_add_spacing().before = value
|
|
|
|
@property
|
|
def spacing_line(self):
|
|
"""
|
|
The value of `w:spacing/@w:line` or |None| if not present.
|
|
"""
|
|
spacing = self.spacing
|
|
if spacing is None:
|
|
return None
|
|
return spacing.line
|
|
|
|
@spacing_line.setter
|
|
def spacing_line(self, value):
|
|
if value is None and self.spacing is None:
|
|
return
|
|
self.get_or_add_spacing().line = value
|
|
|
|
@property
|
|
def spacing_lineRule(self):
|
|
"""
|
|
The value of `w:spacing/@w:lineRule` as a member of the
|
|
:ref:`WdLineSpacing` enumeration. Only the `MULTIPLE`, `EXACTLY`, and
|
|
`AT_LEAST` members are used. It is the responsibility of the client
|
|
to calculate the use of `SINGLE`, `DOUBLE`, and `MULTIPLE` based on
|
|
the value of `w:spacing/@w:line` if that behavior is desired.
|
|
"""
|
|
spacing = self.spacing
|
|
if spacing is None:
|
|
return None
|
|
lineRule = spacing.lineRule
|
|
if lineRule is None and spacing.line is not None:
|
|
return WD_LINE_SPACING.MULTIPLE
|
|
return lineRule
|
|
|
|
@spacing_lineRule.setter
|
|
def spacing_lineRule(self, value):
|
|
if value is None and self.spacing is None:
|
|
return
|
|
self.get_or_add_spacing().lineRule = value
|
|
|
|
@property
|
|
def style(self):
|
|
"""
|
|
String contained in <w:pStyle> child, or None if that element is not
|
|
present.
|
|
"""
|
|
pStyle = self.pStyle
|
|
if pStyle is None:
|
|
return None
|
|
return pStyle.val
|
|
|
|
@style.setter
|
|
def style(self, style):
|
|
"""
|
|
Set val attribute of <w:pStyle> child element to *style*, adding a
|
|
new element if necessary. If *style* is |None|, remove the <w:pStyle>
|
|
element if present.
|
|
"""
|
|
if style is None:
|
|
self._remove_pStyle()
|
|
return
|
|
pStyle = self.get_or_add_pStyle()
|
|
pStyle.val = style
|
|
|
|
@property
|
|
def widowControl_val(self):
|
|
"""
|
|
The value of `widowControl/@val` or |None| if not present.
|
|
"""
|
|
widowControl = self.widowControl
|
|
if widowControl is None:
|
|
return None
|
|
return widowControl.val
|
|
|
|
@widowControl_val.setter
|
|
def widowControl_val(self, value):
|
|
if value is None:
|
|
self._remove_widowControl()
|
|
else:
|
|
self.get_or_add_widowControl().val = value
|
|
|
|
|
|
class CT_Spacing(BaseOxmlElement):
|
|
"""
|
|
``<w:spacing>`` element, specifying paragraph spacing attributes such as
|
|
space before and line spacing.
|
|
"""
|
|
after = OptionalAttribute('w:after', ST_TwipsMeasure)
|
|
before = OptionalAttribute('w:before', ST_TwipsMeasure)
|
|
line = OptionalAttribute('w:line', ST_SignedTwipsMeasure)
|
|
lineRule = OptionalAttribute('w:lineRule', WD_LINE_SPACING)
|
|
|
|
|
|
class CT_TabStop(BaseOxmlElement):
|
|
"""
|
|
``<w:tab>`` element, representing an individual tab stop.
|
|
"""
|
|
val = RequiredAttribute('w:val', WD_TAB_ALIGNMENT)
|
|
leader = OptionalAttribute(
|
|
'w:leader', WD_TAB_LEADER, default=WD_TAB_LEADER.SPACES
|
|
)
|
|
pos = RequiredAttribute('w:pos', ST_SignedTwipsMeasure)
|
|
|
|
|
|
class CT_TabStops(BaseOxmlElement):
|
|
"""
|
|
``<w:tabs>`` element, container for a sorted sequence of tab stops.
|
|
"""
|
|
tab = OneOrMore('w:tab', successors=())
|
|
|
|
def insert_tab_in_order(self, pos, align, leader):
|
|
"""
|
|
Insert a newly created `w:tab` child element in *pos* order.
|
|
"""
|
|
new_tab = self._new_tab()
|
|
new_tab.pos, new_tab.val, new_tab.leader = pos, align, leader
|
|
for tab in self.tab_lst:
|
|
if new_tab.pos < tab.pos:
|
|
tab.addprevious(new_tab)
|
|
return new_tab
|
|
self.append(new_tab)
|
|
return new_tab
|