diff options
Diffstat (limited to 'Master/texmf-dist/asymptote/GUI/InplaceAddObj.py')
-rwxr-xr-x | Master/texmf-dist/asymptote/GUI/InplaceAddObj.py | 179 |
1 files changed, 147 insertions, 32 deletions
diff --git a/Master/texmf-dist/asymptote/GUI/InplaceAddObj.py b/Master/texmf-dist/asymptote/GUI/InplaceAddObj.py index 132969dad19..9bacd5f51fe 100755 --- a/Master/texmf-dist/asymptote/GUI/InplaceAddObj.py +++ b/Master/texmf-dist/asymptote/GUI/InplaceAddObj.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -import PyQt5.QtCore as Qc -import PyQt5.QtGui as Qg -import xasy2asy as x2a +import PyQt5.QtCore as QtCore +import PyQt5.QtGui as QtGui +import xasy2asy as xasy2asy import PrimitiveShape import math @@ -11,9 +11,9 @@ import Widg_addPolyOpt import Widg_addLabel -class InplaceObjProcess(Qc.QObject): - objectCreated = Qc.pyqtSignal(Qc.QObject) - objectUpdated = Qc.pyqtSignal() +class InplaceObjProcess(QtCore.QObject): + objectCreated = QtCore.pyqtSignal(QtCore.QObject) + objectUpdated = QtCore.pyqtSignal() def __init__(self, parent=None): super().__init__(parent) @@ -24,10 +24,10 @@ class InplaceObjProcess(Qc.QObject): def active(self): return self._active - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): raise NotImplementedError - def mouseMove(self, pos, event: Qg.QMouseEvent): + def mouseMove(self, pos, event: QtGui.QMouseEvent): raise NotImplementedError def mouseRelease(self): @@ -45,7 +45,7 @@ class InplaceObjProcess(Qc.QObject): def getXasyObject(self): raise NotImplementedError - def postDrawPreview(self, canvas: Qg.QPainter): + def postDrawPreview(self, canvas: QtGui.QPainter): pass def createOptWidget(self, info): @@ -55,10 +55,10 @@ class InplaceObjProcess(Qc.QObject): class AddCircle(InplaceObjProcess): def __init__(self, parent=None): super().__init__(parent) - self.center = Qc.QPointF(0, 0) + self.center = QtCore.QPointF(0, 0) self.radius = 0 - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) self.radius = 0 self.center.setX(x) @@ -75,9 +75,9 @@ class AddCircle(InplaceObjProcess): def getPreview(self): x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(self.center) - boundRect = Qc.QRectF(x - self.radius, y - self.radius, 2 * self.radius, 2 * self.radius) + boundRect = QtCore.QRectF(x - self.radius, y - self.radius, 2 * self.radius, 2 * self.radius) # because the internal image is flipped... - newPath = Qg.QPainterPath() + newPath = QtGui.QPainterPath() newPath.addEllipse(boundRect) # newPath.addRect(boundRect) return newPath @@ -87,9 +87,9 @@ class AddCircle(InplaceObjProcess): def getXasyObject(self): if self.fill: - newObj = x2a.xasyFilledShape(self.getObject(), None) + newObj = xasy2asy.xasyFilledShape(self.getObject(), None) else: - newObj = x2a.xasyShape(self.getObject(), None) + newObj = xasy2asy.xasyShape(self.getObject(), None) return newObj def forceFinalize(self): @@ -102,8 +102,9 @@ class AddLabel(InplaceObjProcess): self.alignMode = None self.opt = None self.text = None - self.anchor = Qc.QPointF(0, 0) + self.anchor = QtCore.QPointF(0, 0) self._active = False + self.fontSize = 12 def createOptWidget(self, info): self.opt = Widg_addLabel.Widg_addLabel(info) @@ -121,7 +122,7 @@ class AddLabel(InplaceObjProcess): self.anchor.setX(x) self.anchor.setY(y) - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): if self.opt is not None: self.text = self.opt.labelText x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) @@ -140,7 +141,7 @@ class AddLabel(InplaceObjProcess): text = self.text align = str(self.alignMode) anchor = PrimitiveShape.PrimitiveShape.pos_to_tuple(self.anchor) - newLabel = x2a.xasyText(text=text, location=anchor, pen=None, + newLabel = xasy2asy.xasyText(text=text, location=anchor, pen=None, align=align, asyengine=None, fontsize=self.fontSize) newLabel.asyfied = False return newLabel @@ -164,11 +165,11 @@ class AddBezierShape(InplaceObjProcess): # Linkmode should be to the last point. # (x, y, linkmode), (u, v, lm2) <==> (x, y) <=lm2=> (u, v) self.pointsList = [] - self.currentPoint = Qc.QPointF(0, 0) + self.currentPoint = QtCore.QPointF(0, 0) self.pendingPoint = None self.useLegacy = False - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) self.currentPoint.setX(x) self.currentPoint.setY(y) @@ -222,7 +223,7 @@ class AddBezierShape(InplaceObjProcess): # self.updateBasePath() def updateBasePath(self): - self.basePath = x2a.asyPath(asyengine=self.asyengine, forceCurve=self.useBezierBase) + self.basePath = xasy2asy.asyPath(asyengine=self.asyengine, forceCurve=self.useBezierBase) newNode = [(x, y) for x, y, _ in self.pointsList] newLink = [lnk for *args, lnk in self.pointsList[1:]] if self.useLegacy: @@ -237,7 +238,7 @@ class AddBezierShape(InplaceObjProcess): self.basePath.computeControls() def updateBasePathPreview(self): - self.basePathPreview = x2a.asyPath( + self.basePathPreview = xasy2asy.asyPath( asyengine=self.asyengine, forceCurve=self.useBezierBase) newNode = [(x, y) for x, y, _ in self.pointsList] + [(self.currentPoint.x(), self.currentPoint.y())] newLink = [lnk for *args, lnk in self.pointsList[1:]] + [self._getLinkType()] @@ -271,16 +272,16 @@ class AddBezierShape(InplaceObjProcess): def getXasyObject(self): if self.fill: - return x2a.xasyFilledShape(self.getObject(), None) + return xasy2asy.xasyFilledShape(self.getObject(), None) else: - return x2a.xasyShape(self.getObject(), None) + return xasy2asy.xasyShape(self.getObject(), None) class AddPoly(InplaceObjProcess): def __init__(self, parent=None): super().__init__(parent) - self.center = Qc.QPointF(0, 0) - self.currPos = Qc.QPointF(0, 0) + self.center = QtCore.QPointF(0, 0) + self.currPos = QtCore.QPointF(0, 0) self.sides = None self.inscribed = None self.centermode = None @@ -288,18 +289,18 @@ class AddPoly(InplaceObjProcess): self.fill = None self.opt = None - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): self._active = True self.sides = info['sides'] self.inscribed = info['inscribed'] self.centermode = info['centermode'] self.fill = info['fill'] - + x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) self.center.setX(x) self.center.setY(y) - self.currPos = Qc.QPointF(self.center) + self.currPos = QtCore.QPointF(self.center) def mouseMove(self, pos, event): x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) @@ -329,7 +330,7 @@ class AddPoly(InplaceObjProcess): else: poly = PrimitiveShape.PrimitiveShape.exscribedRegPolygon(self.sides, self.center, self._rad(), self._angle(), qpoly=True) - newPath = Qg.QPainterPath() + newPath = QtGui.QPainterPath() newPath.addPolygon(poly) return newPath @@ -350,7 +351,121 @@ class AddPoly(InplaceObjProcess): def getXasyObject(self): if self.fill: - newObj = x2a.xasyFilledShape(self.getObject(), None) + newObj = xasy2asy.xasyFilledShape(self.getObject(), None) else: - newObj = x2a.xasyShape(self.getObject(), None) + newObj = xasy2asy.xasyShape(self.getObject(), None) return newObj + +class AddFreehand(InplaceObjProcess): + # TODO: At the moment this is just a copy-paste of the AddBezierObj. + # Must find a better algorithm for constructing the obj rather than + # a node for every pixel the mouse moves. + def __init__(self, parent=None): + super().__init__(parent) + self.asyengine = None + self.basePath = None + self.basePathPreview = None + self.closedPath = None + self.info = None + self.fill = False + self.opt = None + + # list of "committed" points with Linkage information. + # Linkmode should be to the last point. + # (x, y, linkmode), (u, v, lm2) <==> (x, y) <=lm2=> (u, v) + self.pointsList = [] + self.currentPoint = QtCore.QPointF(0, 0) + self.pendingPoint = None + self.useLegacy = False + + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): + x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) + self.currentPoint.setX(x) + self.currentPoint.setY(y) + self.info = info + + if not self._active: + self._active = True + self.fill = info['fill'] + self.asyengine = info['asyengine'] + self.closedPath = info['closedPath'] + self.useBezierBase = info['useBezier'] + self.useLegacy = self.info['options']['useLegacyDrawMode'] + self.pointsList.clear() + self.pointsList.append((x, y, None)) + else: + # see http://doc.qt.io/archives/qt-4.8/qt.html#MouseButton-enum + if (int(mouseEvent.buttons()) if mouseEvent is not None else 0) & 0x2 and self.useLegacy: + self.forceFinalize() + + def _getLinkType(self): + if self.info['useBezier']: + return '..' + else: + return '--' + + def mouseMove(self, pos, event): + # in postscript coords. + if self._active: + x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) + + if self.useLegacy or int(event.buttons()) != 0: + self.currentPoint.setX(x) + self.currentPoint.setY(y) + self.pointsList.append((x, y, self._getLinkType())) + + + def createOptWidget(self, info): + return None + + def mouseRelease(self): + self.updateBasePath() + self._active = False + self.pointsList.clear() + self.objectCreated.emit(self.getXasyObject()) + self.basePath = None + + def updateBasePath(self): + self.basePath = xasy2asy.asyPath(asyengine=self.asyengine, forceCurve=self.useBezierBase) + newNode = [(x, y) for x, y, _ in self.pointsList] + newLink = [lnk for *args, lnk in self.pointsList[1:]] + if self.useLegacy: + newNode += [(self.currentPoint.x(), self.currentPoint.y())] + newLink += [self._getLinkType()] + if self.closedPath: + newNode.append('cycle') + newLink.append(self._getLinkType()) + self.basePath.initFromNodeList(newNode, newLink) + + if self.useBezierBase: + self.basePath.computeControls() + + def updateBasePathPreview(self): + self.basePathPreview = xasy2asy.asyPath( + asyengine=self.asyengine, forceCurve=self.useBezierBase) + newNode = [(x, y) for x, y, _ in self.pointsList] + [(self.currentPoint.x(), self.currentPoint.y())] + newLink = [lnk for *args, lnk in self.pointsList[1:]] + [self._getLinkType()] + if self.closedPath: + newNode.append('cycle') + newLink.append(self._getLinkType()) + self.basePathPreview.initFromNodeList(newNode, newLink) + + if self.useBezierBase: + self.basePathPreview.computeControls() + + def getObject(self): + if self.basePath is None: + raise RuntimeError('BasePath is None') + self.basePath.asyengine = self.asyengine + return self.basePath + + def getPreview(self): + if self._active: + if self.pointsList: + self.updateBasePathPreview() + newPath = self.basePathPreview.toQPainterPath() + return newPath + + def getXasyObject(self): + self.fill = False + return xasy2asy.xasyShape(self.getObject(), None) |