diff options
Diffstat (limited to 'Build/source/utils/asymptote/GUI/labelEditor.py')
-rw-r--r-- | Build/source/utils/asymptote/GUI/labelEditor.py | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/GUI/labelEditor.py b/Build/source/utils/asymptote/GUI/labelEditor.py new file mode 100644 index 00000000000..76bc8d7d0a1 --- /dev/null +++ b/Build/source/utils/asymptote/GUI/labelEditor.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 + +from pyUIClass.labelTextEditor import Ui_Dialog +import PyQt5.QtWidgets as Qw +import PyQt5.QtSvg as Qs +import PyQt5.QtGui as Qg +import PyQt5.QtCore as Qc +import xasyArgs as xa +import xasy2asy as x2a +import subprocess +import xasyOptions as xo +import xasyUtils as xu +import tempfile +import uuid +import os +import io + + +class labelEditor(Qw.QDialog): + def __init__(self, text=''): + super().__init__() + self.ui = Ui_Dialog() + self.ui.setupUi(self) + + self.ui.btnAccept.clicked.connect(self.accept) + self.ui.btnCancel.clicked.connect(self.reject) + self.ui.chkMathMode.stateChanged.connect(self.chkMathModeChecked) + self.ui.btnPreview.clicked.connect(self.btnPreviewOnClick) + self.ui.btnGetText.clicked.connect(self.btnGetTextOnClick) + + self.svgPreview = None + self.initializeText(text) + + def initializeText(self, text: str): + if text[0] == '$' and text[-1] == '$': + self.ui.chkMathMode.setChecked(True) + text = text.strip('$') + + if text.startswith('\\displaystyle{'): + self.ui.cmbMathStyle.setCurrentText('Display Style') + text = text.rstrip('}') + text = text.replace('\\displaystyle{', '', 1) + elif text.startswith('\\scriptstyle{'): + self.ui.cmbMathStyle.setCurrentText('Script Style') + text = text.rstrip('}') + text = text.replace('\\scriptstyle{', '', 1) + + self.ui.txtLabelEdit.setPlainText(text) + + def chkMathModeChecked(self, checked): + self.ui.cmbMathStyle.setEnabled(checked) + + def getText(self): + rawText = self.ui.txtLabelEdit.toPlainText() + rawText.replace('\n', ' ') + if self.ui.chkMathMode.isChecked(): + prefix = '' + suffix = '' + if self.ui.cmbMathStyle.currentText() == 'Display Style': + prefix = '\\displaystyle{' + suffix = '}' + elif self.ui.cmbMathStyle.currentText() == 'Script Style': + prefix = '\\scriptstyle{' + suffix = '}' + return '${0}{1}{2}$'.format(prefix, rawText, suffix) + else: + return rawText + + def btnPreviewOnClick(self): + path = xa.getArgs().asypath + if path is None: + opt = xo.xasyOptions().load() + path = opt['asyPath'] + + asyInput = """ + frame f; + label(f, "{0}"); + write(min(f), newl); + write(max(f), newl); + shipout(f); + """ + + self.svgPreview = Qs.QSvgRenderer() + with tempfile.TemporaryDirectory(prefix='xasylbl_') as tmpdir: + id = str(uuid.uuid4()) + tmpFile = os.path.join(tmpdir, 'lbl-{0}.svg'.format(id)) + + with subprocess.Popen(args=[path, '-fsvg', '-o', tmpFile, '-'], encoding='utf-8', stdin=subprocess.PIPE, + stdout=subprocess.PIPE) as asy: + asy.stdin.write(asyInput.format(self.getText())) + asy.stdin.close() + out = asy.stdout.read() + + raw_array = out.splitlines() + + bounds_1, bounds_2 = [val.strip() for val in raw_array] + + min_bounds = xu.listize(bounds_1, (float, float)) + max_bounds = xu.listize(bounds_2, (float, float)) + + new_rect = self.processBounds(min_bounds, max_bounds) + self.svgPreview.load(tmpFile) + + + + self.drawPreview(new_rect) + + def drawPreview(self, naturalBounds): + img = Qg.QPixmap(self.ui.lblLabelPreview.size()) + img.fill(Qg.QColor.fromRgbF(1, 1, 1, 1)) + if self.svgPreview is None: + pass + else: + with Qg.QPainter(img) as pnt: + scale_ratio = self.getIdealScaleRatio(naturalBounds, self.ui.lblLabelPreview.rect()) + + pnt.translate(self.ui.lblLabelPreview.rect().center()) + pnt.scale(scale_ratio, scale_ratio) + self.svgPreview.render(pnt, naturalBounds) + self.ui.lblLabelPreview.setPixmap(img) + + + def getIdealScaleRatio(self, rect, boundsRect): + assert isinstance(rect, (Qc.QRect, Qc.QRectF)) + assert isinstance(rect, (Qc.QRect, Qc.QRectF)) + + magic_ratio = 0.50 + idealRatioHeight = (magic_ratio * boundsRect.height()) / rect.height() + magicRatioWidth = 0.50 + + if idealRatioHeight * rect.width() > magicRatioWidth * boundsRect.width(): + idealRatioWidth = (magicRatioWidth * boundsRect.width()) / rect.width() + idealRatio = min(idealRatioHeight, idealRatioWidth) + else: + idealRatio = idealRatioHeight + return idealRatio + + def processBounds(self, minPt, maxPt): + p1x, p1y = minPt + p2x, p2y = maxPt + + minPt = Qc.QPointF(p1x, p1y) + maxPt = Qc.QPointF(p2x, p2y) + + newRect = Qc.QRectF(minPt, maxPt) + return newRect + + + def btnGetTextOnClick(self): + msgbox = Qw.QMessageBox() + msgbox.setText('Text Preview:\n' + self.getText()) + msgbox.setWindowTitle('Text preview') + msgbox.show() + return msgbox.exec_() |