Files
Igor20264 516abe7b83
Python application / build (push) Has been cancelled
BigUpdate
2026-09-03 10:44:08 +03:00

92 lines
3.4 KiB
Python

from typing import Generator
from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT
from docx.oxml import CT_Tbl
from docx.shared import Pt, Twips
from docx.table import Table
from docx.text.paragraph import Paragraph as DocxParagraph
from .requires_numbering import RequiresNumbering
from ..layout_tracker import LayoutState
from ..renderable import Renderable
from ..rendered_info import RenderedInfo
from ..util import create_element
from ..latex_math import latex_to_omml
_HEIGHT = Pt(50)
class Equation(Renderable, RequiresNumbering):
def __init__(self, parent, latex_formula: str, unique_name: str | None = None,
numbered: bool = False):
super().__init__("Формула")
self.unique_name = unique_name
self._numbered = numbered
word_math = latex_to_omml(latex_formula)
sect = parent.part.document.sections[0]
left_margin = Twips(int(
parent.part.styles["Normal Table"]._element.xpath("w:tblPr/w:tblCellMar/w:left")[0].attrib[
"{http://schemas.openxmlformats.org/wordprocessingml/2006/main}w"]))
right_margin = Twips(int(
parent.part.styles["Normal Table"]._element.xpath("w:tblPr/w:tblCellMar/w:right")[0].attrib[
"{http://schemas.openxmlformats.org/wordprocessingml/2006/main}w"]))
table_width = sect.page_width - sect.right_margin - sect.left_margin + left_margin + right_margin
self._parent = parent
self._table = table = Table(CT_Tbl.new_tbl(1, 2, table_width), parent)
left_cell = table.cell(0, 0)
right_cell = table.cell(0, 1)
right_cell.width = Pt(40)
left_cell.width = table_width - right_cell.width
table.rows[0].height = _HEIGHT
left_paragraph = left_cell.paragraphs[0]
left_paragraph.style = "Formula Content"
left_paragraph._p.append(word_math)
left_cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
self._right_paragraph = right_cell.paragraphs[0]
self._right_paragraph.style = "Formula Numbering"
self._number_text = "?"
right_cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
self._spacer_before = create_element("w:p")
self._spacer_after = create_element("w:p")
def enable_numbering(self):
self._numbered = True
@property
def needs_numbering(self) -> bool:
return self._numbered
def set_number(self, number: str):
self._number_text = str(number)
self._numbered = True
# Rebuild right cell content
p = self._right_paragraph._p
for child in list(p):
if child.tag.endswith("}r"):
p.remove(child)
p.append(create_element("w:r", "("))
p.append(create_element("w:r", self._number_text))
p.append(create_element("w:r", ")"))
def render(self, previous_rendered: RenderedInfo, layout_state: LayoutState) -> Generator[
"RenderedInfo | Renderable", None, None]:
spacer_h = Pt(21) # ~ one empty line at 14pt * 1.5
height = _HEIGHT + spacer_h * 2
if height > layout_state.remaining_page_height:
height += layout_state.remaining_page_height
yield RenderedInfo(DocxParagraph(self._spacer_before, self._parent), spacer_h)
yield RenderedInfo(self._table, _HEIGHT)
yield RenderedInfo(DocxParagraph(self._spacer_after, self._parent), spacer_h)