aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrien Tétar2015-10-10 18:41:33 +0200
committerAdrien Tétar2015-10-10 18:41:33 +0200
commitbd72f20da531207c16f5967101a230ca12e84657 (patch)
treef64430b3b10d44195539ffcdd79ccb5dfd9596b1
parenta37c85e39a38fe11efbd7df3c1cf4fce5a84a7c9 (diff)
downloadtrufont-bd72f20da531207c16f5967101a230ca12e84657.tar.bz2
glyphView: layers support, fontView: change UFO open behavior, various
-rw-r--r--Lib/defconQt/fontView.py25
-rw-r--r--Lib/defconQt/glyphCollectionView.py18
-rw-r--r--Lib/defconQt/glyphView.py128
-rw-r--r--Lib/defconQt/spaceCenter.py2
4 files changed, 137 insertions, 36 deletions
diff --git a/Lib/defconQt/fontView.py b/Lib/defconQt/fontView.py
index 38cc054..e8e110f 100644
--- a/Lib/defconQt/fontView.py
+++ b/Lib/defconQt/fontView.py
@@ -5,7 +5,7 @@ from defconQt.glyphView import MainGfxWindow
from defconQt.groupsView import GroupsWindow
from defconQt.scriptingWindow import MainScriptingWindow
from defconQt.objects.defcon import CharacterSet, TFont, TGlyph
-from defcon import Component
+from defcon import Color, Component
from defconQt.spaceCenter import MainSpaceWindow
# TODO: remove globs when things start to stabilize
from PyQt5.QtCore import *
@@ -551,7 +551,6 @@ class MainWindow(QMainWindow):
self.font = font
self.collectionWidget.characterSelectedCallback = self._selectionChanged
self.collectionWidget.doubleClickCallback = self._glyphOpened
- # XXX: should spaceCenter have this functionality as well?
# TODO: should default be True or False?
self.collectionWidget.updateCurrentGlyph = True
self.collectionWidget.setFocus()
@@ -660,8 +659,12 @@ class MainWindow(QMainWindow):
def openFile(self, path=None):
if not path:
+ if sys.platform == "darwin":
+ fileFormats = "UFO Fonts (*.ufo)"
+ else:
+ fileFormats = "UFO Fonts (metainfo.plist)"
path, ok = QFileDialog.getOpenFileName(self, "Open File", '',
- "UFO Fonts (metainfo.plist)")
+ fileFormats)
if not ok: return
if path:
if ".plist" in path:
@@ -781,14 +784,13 @@ class MainWindow(QMainWindow):
def maybeSaveBeforeExit(self):
if self.font.dirty:
- title = "Me"
if self.font.path is not None:
# TODO: maybe cache this font name in the Font
currentFont = os.path.basename(self.font.path.rstrip(os.sep))
else:
currentFont = "Untitled.ufo"
body = "Do you want to save the changes you made to “%s”?" % currentFont
- closeDialog = QMessageBox(QMessageBox.Question, title, body,
+ closeDialog = QMessageBox(QMessageBox.Question, None, body,
QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, self)
closeDialog.setInformativeText("Your changes will be lost if you don’t save them.")
closeDialog.setModal(True)
@@ -913,11 +915,7 @@ class MainWindow(QMainWindow):
glyphs = self.collectionWidget.glyphs
for key in self.collectionWidget.selection:
glyph = glyphs[key]
- if color is None:
- if "public.markColor" in glyph.lib:
- del glyph.lib["public.markColor"]
- else:
- glyph.lib["public.markColor"] = ",".join(str(c) for c in color.getRgbF())
+ glyph.markColor = Color(color.getRgbF() if color is not None else None)
def _fontChanged(self, notification):
self.collectionWidget.update()
@@ -1051,11 +1049,12 @@ class MainWindow(QMainWindow):
self.sortDescriptor = self.sortDescriptor
def about(self):
- QMessageBox.about(self, "About Me",
- "<h3>About Me</h3>" \
+ name = QApplication.applicationName()
+ QMessageBox.about(self, "About {}".format(name),
+ "<h3>About {}</h3>" \
"<p>I am a new UFO-centric font editor and I aim to bring the <b>robofab</b> " \
"ecosystem to all main operating systems, in a fast and dependency-free " \
- "package.</p>")
+ "package.</p>".format(name))
class SettingsDialog(QDialog):
def __init__(self, parent=None):
diff --git a/Lib/defconQt/glyphCollectionView.py b/Lib/defconQt/glyphCollectionView.py
index 687d76f..81d35f9 100644
--- a/Lib/defconQt/glyphCollectionView.py
+++ b/Lib/defconQt/glyphCollectionView.py
@@ -399,18 +399,12 @@ class GlyphCollectionWidget(QWidget):
linesColor = cellHeaderHighlightLineColor
# mark color
if not glyph.template:
- # TODO: fetch via defcon dict
- if "public.markColor" in glyph.lib:
- colorStr = glyph.lib["public.markColor"].split(",")
- if len(colorStr) == 4:
- comp = []
- for c in colorStr:
- comp.append(float(c.strip()))
- markColor = QColor.fromRgbF(*comp)
- markGradient.setColorAt(1.0, markColor)
- markGradient.setColorAt(0.0, markColor.lighter(125))
- painter.fillRect(0, GlyphCellHeaderHeight, self.squareSize,
- self.squareSize - GlyphCellHeaderHeight, QBrush(markGradient))
+ if glyph.markColor is not None:
+ markColor = QColor.fromRgbF(*tuple(glyph.markColor))
+ markGradient.setColorAt(1.0, markColor)
+ markGradient.setColorAt(0.0, markColor.lighter(125))
+ painter.fillRect(0, GlyphCellHeaderHeight, self.squareSize,
+ self.squareSize - GlyphCellHeaderHeight, QBrush(markGradient))
if glyph.dirty:
brushColor = dirtyGradient
linesColor = cellHeaderHighlightLineColor.darker(110)
diff --git a/Lib/defconQt/glyphView.py b/Lib/defconQt/glyphView.py
index d7968ed..02a6994 100644
--- a/Lib/defconQt/glyphView.py
+++ b/Lib/defconQt/glyphView.py
@@ -125,7 +125,7 @@ class AddAnchorDialog(QDialog):
self.setLayout(layout)
@classmethod
- def getNewAnchorData(cls, parent, pos=None):
+ def getNewAnchorName(cls, parent, pos=None):
dialog = cls(pos, parent)
result = dialog.exec_()
name = dialog.anchorNameEdit.text()
@@ -138,6 +138,36 @@ class AddComponentDialog(GotoDialog):
self._sortedGlyphs.remove(args[0].name)
self.updateGlyphList(False)
+class AddLayerDialog(QDialog):
+ def __init__(self, parent=None):
+ super(AddLayerDialog, self).__init__(parent)
+ self.setWindowModality(Qt.WindowModal)
+ self.setWindowTitle("Add layer…")
+
+ layout = QGridLayout(self)
+
+ layerNameLabel = QLabel("Layer name:", self)
+ self.layerNameEdit = QLineEdit(self)
+ self.layerNameEdit.setFocus(True)
+
+ buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
+ buttonBox.accepted.connect(self.accept)
+ buttonBox.rejected.connect(self.reject)
+
+ l = 0
+ layout.addWidget(layerNameLabel, l, 0)
+ layout.addWidget(self.layerNameEdit, l, 1)
+ l += 1
+ layout.addWidget(buttonBox, l, 2)
+ self.setLayout(layout)
+
+ @classmethod
+ def getNewLayerName(cls, parent):
+ dialog = cls(parent)
+ result = dialog.exec_()
+ name = dialog.layerNameEdit.text()
+ return (name, result)
+
class MainGfxWindow(QMainWindow):
def __init__(self, glyph, parent=None):
super(MainGfxWindow, self).__init__(parent)
@@ -157,6 +187,7 @@ class MainGfxWindow(QMainWindow):
toolBar = QToolBar(self)
toolBar.setMovable(False)
+ toolBar.setContentsMargins(2, 0, 2, 0)
selectionToolButton = toolBar.addAction("Selection", self.view.setSceneSelection)
selectionToolButton.setCheckable(True)
selectionToolButton.setChecked(True)
@@ -170,6 +201,11 @@ class MainGfxWindow(QMainWindow):
knifeToolButton = toolBar.addAction("Knife", self.view.setSceneKnife)
knifeToolButton.setCheckable(True)
knifeToolButton.setIcon(QIcon("defconQt/resources/cut.svg"))
+ # http://www.setnode.com/blog/right-aligning-a-button-in-a-qtoolbar/
+ spacer = QWidget()
+ spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ toolBar.addWidget(spacer)
+ toolBar.addWidget(self.view.currentLayerBox())
toolsGroup = QActionGroup(self)
toolsGroup.addAction(selectionToolButton)
toolsGroup.addAction(penToolButton)
@@ -177,10 +213,6 @@ class MainGfxWindow(QMainWindow):
toolsGroup.addAction(knifeToolButton)
self.addToolBar(toolBar)
- self.setCentralWidget(self.view)
- self.setWindowTitle(glyph.name, glyph.getParent())
- self.adjustSize()
-
self.setContextMenuPolicy(Qt.ActionsContextMenu)
createAnchorAction = QAction("Add Anchor…", self)
createAnchorAction.triggered.connect(self.view.createAnchor)
@@ -189,6 +221,10 @@ class MainGfxWindow(QMainWindow):
createComponentAction.triggered.connect(self.view.createComponent)
self.addAction(createComponentAction)
+ self.setCentralWidget(self.view)
+ self.setWindowTitle(glyph.name, glyph.getParent())
+ self.adjustSize()
+
def changeGlyph(self):
glyph = self.view._glyph
newGlyph, ok = GotoDialog.getNewGlyph(self, glyph)
@@ -748,6 +784,12 @@ class GlyphScene(QGraphicsScene):
self._blocked = False
+ def _get_glyphObject(self):
+ view = self.views()[0]
+ return view._glyph
+
+ _glyphObject = property(_get_glyphObject, doc="Get the current glyph in the view.")
+
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.acceptProposedAction()
@@ -1285,6 +1327,7 @@ class GlyphView(QGraphicsView):
super(GlyphView, self).__init__(parent)
self._glyph = glyph
self._glyph.addObserver(self, "_glyphChanged", "Glyph.Changed")
+ self._glyph.layerSet.addObserver(self, "_layersChanged", "LayerSet.Changed")
self._impliedPointSize = 1000
self._pointSize = None
@@ -1303,6 +1346,9 @@ class GlyphView(QGraphicsView):
font.setFixedPitch(True)
self.setFont(font)
+ self._currentLayerBox = QComboBox(self)
+ self._currentLayerBox.currentIndexChanged.connect(self._currentLayerChanged)
+
self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
#self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate)
@@ -1315,11 +1361,15 @@ class GlyphView(QGraphicsView):
self.addBackground()
self.addBlues()
self.addHorizontalMetrics()
+ self.addOtherLayersOutlines()
self.addOutlines()
self.addComponents()
self.addAnchors()
self.addPoints()
+ def currentLayerBox(self):
+ return self._currentLayerBox
+
def _glyphChanged(self, notification):
# TODO: maybe detect sidebearing changes (space center) and then only
# translate elements rather than reconstructing them.
@@ -1327,6 +1377,11 @@ class GlyphView(QGraphicsView):
# sp.center values.
self.redrawGlyph()
+ # TODO: diagnose notifications count
+ def _layersChanged(self, notification):
+ self.redrawGlyph()
+ self.redrawOtherLayers()
+
def redrawGlyph(self):
path = self._glyph.getRepresentation("defconQt.NoComponentsQPainterPath")
scene = self.scene()
@@ -1346,6 +1401,14 @@ class GlyphView(QGraphicsView):
# this will not be the case anymore when drag sidebearings pops up
scene._widthItem.setRect(0, -1000, self._glyph.width, 3000)
+ def redrawOtherLayers(self):
+ scene = self.scene()
+ for item in scene.items():
+ # XXX: discriminate better
+ if isinstance(item, QGraphicsPathItem) and item.zValue() == -997:
+ scene.removeItem(item)
+ self.addOtherLayersOutlines()
+
def addBackground(self):
scene = self.scene()
font = self._glyph.getParent()
@@ -1409,16 +1472,38 @@ class GlyphView(QGraphicsView):
item = VGuidelinesTextItem(text, font)
item.setBrush(metricsColor)
item.setFlag(QGraphicsItem.ItemIgnoresTransformations)
- item.setPos(width, y) # XXX
+ item.setPos(width, y)
item.setZValue(-997)
scene.addItem(item)
+ def addOtherLayersOutlines(self):
+ comboBox = self._currentLayerBox
+ comboBox.blockSignals(True)
+ comboBox.clear()
+ scene = self.scene()
+ layerSet = self._glyph.layerSet
+ for layer in layerSet:
+ comboBox.addItem(layer.name, layer)
+ if layer == self._glyph.layer:
+ comboBox.setCurrentText(layer.name)
+ continue
+ if not self._glyph.name in layer:
+ continue
+ path = layer[self._glyph.name].getRepresentation("defconQt.NoComponentsQPainterPath")
+ if layer.color is not None:
+ layerColor = QColor.fromRgbF(tuple(layer.color))
+ else:
+ layerColor = Qt.black
+ item = scene.addPath(path, QPen(layerColor))
+ item.setZValue(-997)
+ comboBox.addItem("New layer...", None)
+ comboBox.blockSignals(False)
+
def addOutlines(self):
scene = self.scene()
path = self._glyph.getRepresentation("defconQt.NoComponentsQPainterPath")
scene._outlineItem = scene.addPath(path, brush=QBrush(fillColor))
scene._outlineItem.setZValue(-995)
- scene._glyphObject = self._glyph
def addComponents(self):
scene = self.scene()
@@ -1532,7 +1617,7 @@ class GlyphView(QGraphicsView):
if scene._integerPlane:
pos.setX(int(pos.x()))
pos.setY(int(pos.y()))
- newAnchorName, ok = AddAnchorDialog.getNewAnchorData(self, pos)
+ newAnchorName, ok = AddAnchorDialog.getNewAnchorName(self, pos)
if ok:
anchor = Anchor()
anchor.x = pos.x()
@@ -1547,21 +1632,44 @@ class GlyphView(QGraphicsView):
component.baseGlyph = newGlyph.name
self._glyph.appendComponent(component)
+ def _currentLayerChanged(self, newLayerIndex):
+ comboBox = self.sender()
+ newLayer = comboBox.itemData(newLayerIndex)
+ if newLayer is None:
+ # add a new layer
+ newLayerName, ok = AddLayerDialog.getNewLayerName(self)
+ if ok:
+ self._glyph.layerSet.newLayer(newLayerName)
+ self._currentLayerBox.blockSignals(True)
+ self._currentLayerBox.setCurrentText(newLayerName)
+ self._currentLayerBox.blockSignals(False)
+ newLayer = self._glyph.layerSet[newLayerName]
+ else:
+ return
+ if not self._glyph.name in newLayer:
+ newLayer.newGlyph(self._glyph.name)
+ # TODO: generalize this out, can’t use newStandardGlyph unfortunately
+ newLayer[self._glyph.name].width = self._glyph.width
+ newLayer[self._glyph.name].template = True
+ newGlyph = newLayer[self._glyph.name]
+ self.setGlyph(newGlyph)
+
def setGlyph(self, glyph):
scene = self.scene()
self._glyph.removeObserver(self, "Glyph.Changed")
+ self._glyph.layerSet.removeObserver(self, "LayerSet.Changed")
# TODO: consider creating a new scene instead of zeroing things out
# manually
scene._dataForUndo = []
scene._dataForRedo = []
self._glyph = glyph
- # XXX: DRY ALERT!
- scene._glyphObject = glyph
app = QApplication.instance()
app.setCurrentGlyph(glyph)
self._glyph.addObserver(self, "_glyphChanged", "Glyph.Changed")
+ self._glyph.layerSet.addObserver(self, "_layersChanged", "LayerSet.Changed")
self.parent().setWindowTitle(self._glyph.name, self._glyph.getParent())
self.redrawGlyph()
+ self.redrawOtherLayers()
def showEvent(self, event):
super(GlyphView, self).showEvent(event)
diff --git a/Lib/defconQt/spaceCenter.py b/Lib/defconQt/spaceCenter.py
index 4224979..d588ef8 100644
--- a/Lib/defconQt/spaceCenter.py
+++ b/Lib/defconQt/spaceCenter.py
@@ -142,7 +142,7 @@ class MainSpaceWindow(QWidget):
glyphName = self.font.unicodeData.glyphNameForUnicode(ord(c))
glyphNames.append(glyphName)
# catch remaining compile.
- if compileStack is not None:
+ if compileStack is not None and compileStack:
catchCompile()
return glyphNames