summaryrefslogtreecommitdiff
path: root/graphics/asymptote/GUI/labelEditor.py
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/asymptote/GUI/labelEditor.py')
-rw-r--r--graphics/asymptote/GUI/labelEditor.py154
1 files changed, 154 insertions, 0 deletions
diff --git a/graphics/asymptote/GUI/labelEditor.py b/graphics/asymptote/GUI/labelEditor.py
new file mode 100644
index 0000000000..76bc8d7d0a
--- /dev/null
+++ b/graphics/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_()