diff options
| author | Adrien Tétar | 2015-07-01 10:13:38 +0200 |
|---|---|---|
| committer | Adrien Tétar | 2015-07-01 10:13:38 +0200 |
| commit | 2cb5646c5c49258398ad346bd1a975c6b9c79bd6 (patch) | |
| tree | a66794ab0e9a5b532239c8e9d7a8548344de67d9 /Lib | |
| parent | f61fceb21c8d4657f9394517cf6fb65523161e47 (diff) | |
| download | trufont-2cb5646c5c49258398ad346bd1a975c6b9c79bd6.tar.bz2 | |
spaceCenter: show active letter bbox, allow opening glyphView, showMetrics, verticalFlip, proportional scrolling, enforce int spacing values in the widget, nits
Diffstat (limited to 'Lib')
| -rw-r--r-- | Lib/defconQt/fontView.py | 2 | ||||
| -rw-r--r-- | Lib/defconQt/glyphView.py | 7 | ||||
| -rw-r--r-- | Lib/defconQt/groupsView.py | 1 | ||||
| -rw-r--r-- | Lib/defconQt/spaceCenter.py | 205 |
4 files changed, 166 insertions, 49 deletions
diff --git a/Lib/defconQt/fontView.py b/Lib/defconQt/fontView.py index 262e24b..a4f1e5c 100644 --- a/Lib/defconQt/fontView.py +++ b/Lib/defconQt/fontView.py @@ -611,7 +611,7 @@ class MainWindow(QMainWindow): action = self.sender() self.characterWidget.markSelection(action.data()) - def _fontChanged(self, event): + def _fontChanged(self, notification): self.characterWidget.update() def _glyphOpened(self, name): diff --git a/Lib/defconQt/glyphView.py b/Lib/defconQt/glyphView.py index f8b6303..728c677 100644 --- a/Lib/defconQt/glyphView.py +++ b/Lib/defconQt/glyphView.py @@ -82,8 +82,8 @@ class MainGfxWindow(QMainWindow): self.view._glyph.removeObserver(self, "Glyph.Changed") super(GlyphView, self).close() - def _glyphChanged(self, event): - self.view._glyphChanged(event) + def _glyphChanged(self, notification): + self.view._glyphChanged(notification) def setRenderer(self, action): if action == self.nativeAction: @@ -163,7 +163,6 @@ class OffCurvePointItem(QGraphicsEllipseItem): value.setY(copysign(avg, value.y())) else: value.setY(0) - elif change == QGraphicsItem.ItemPositionHasChanged: self.parentItem()._CPMoved(value) return value @@ -734,7 +733,7 @@ class GlyphView(QGraphicsView): #self.scale(sc, sc); #self.scene().setSceneRect(-1000, -1000, 3000, 3000) - def _glyphChanged(self, event): + def _glyphChanged(self, notification): path = self._glyph.getRepresentation("defconQt.NoComponentsQPainterPath") self.scene()._outlineItem.setPath(path) self.scene()._outlineItem.update() diff --git a/Lib/defconQt/groupsView.py b/Lib/defconQt/groupsView.py index dae9b42..75b7b10 100644 --- a/Lib/defconQt/groupsView.py +++ b/Lib/defconQt/groupsView.py @@ -6,6 +6,7 @@ from PyQt5.QtWidgets import * class GroupListWidget(QListWidget): def __init__(self, groupNames, parent=None): super(GroupListWidget, self).__init__(parent) + #self.setAlternatingRowColors(True) self.setSelectionMode(QAbstractItemView.SingleSelection) self.setSortingEnabled(True) diff --git a/Lib/defconQt/spaceCenter.py b/Lib/defconQt/spaceCenter.py index f0375da..3920d03 100644 --- a/Lib/defconQt/spaceCenter.py +++ b/Lib/defconQt/spaceCenter.py @@ -1,10 +1,13 @@ -from PyQt5.QtCore import QAbstractTableModel, QEvent, QSize, Qt -from PyQt5.QtGui import (QBrush, QColor, QFont, QIcon, QKeySequence, QLinearGradient, QPainter, - QPainterPath, QPalette, QPen) -from PyQt5.QtWidgets import (QAbstractItemView, QActionGroup, QApplication, QComboBox, QGridLayout, QLabel, QLineEdit, - QMainWindow, QMenu, QPushButton, QScrollArea, QStyledItemDelegate, QTableView, QTableWidget, QTableWidgetItem, QVBoxLayout, QSizePolicy, QSpinBox, QToolBar, QWidget) +from fontView import cellSelectionColor +from PyQt5.QtCore import *#QAbstractTableModel, QEvent, QSize, Qt +from PyQt5.QtGui import *#(QBrush, QColor, QFont, QIcon, QKeySequence, QLinearGradient, QPainter, + #QPainterPath, QPalette, QPen) +from PyQt5.QtWidgets import *#(QAbstractItemView, QActionGroup, QApplication, QComboBox, QGridLayout, QLabel, QLineEdit, + #QMainWindow, QMenu, QPushButton, QScrollArea, QStyledItemDelegate, QTableView, QTableWidget, QTableWidgetItem, QVBoxLayout, QSizePolicy, QSpinBox, QToolBar, QWidget) defaultPointSize = 150 +glyphSelectionColor = QColor(cellSelectionColor) +glyphSelectionColor.setAlphaF(.09) class MainSpaceWindow(QWidget): def __init__(self, font, string=None, pointSize=defaultPointSize, parent=None): @@ -53,10 +56,10 @@ class MainSpaceWindow(QWidget): self._unsubscribeFromGlyphs() super(MainSpaceWindow, self).close() - def _fontInfoChanged(self, event): + def _fontInfoChanged(self, notification): self.canvas.update() - def _glyphChanged(self, event): + def _glyphChanged(self, notification): self.canvas.update() self.table.blockSignals(True) self.table.fillGlyphs() @@ -172,11 +175,16 @@ class FontToolBar(QToolBar): self.toolsMenu = QMenu(self) showKerning = self.toolsMenu.addAction("Show Kerning", self.showKerning) showKerning.setCheckable(True) + showMetrics = self.toolsMenu.addAction("Show Metrics", self.showMetrics) + showMetrics.setCheckable(True) self.toolsMenu.addSeparator() wrapLines = self.toolsMenu.addAction("Wrap lines", self.wrapLines) wrapLines.setCheckable(True) noWrapLines = self.toolsMenu.addAction("No wrap", self.noWrapLines) noWrapLines.setCheckable(True) + self.toolsMenu.addSeparator() + verticalFlip = self.toolsMenu.addAction("Vertical flip", self.verticalFlip) + verticalFlip.setCheckable(True) wrapLinesGroup = QActionGroup(self) wrapLinesGroup.addAction(wrapLines) @@ -193,6 +201,14 @@ class FontToolBar(QToolBar): action = self.sender() self.parent().canvas.setShowKerning(action.isChecked()) + def showMetrics(self): + action = self.sender() + self.parent().canvas.setShowMetrics(action.isChecked()) + + def verticalFlip(self): + action = self.sender() + self.parent().canvas.setVerticalFlip(action.isChecked()) + def wrapLines(self): self.parent().canvas.setWrapLines(True) @@ -215,6 +231,10 @@ class GlyphsCanvas(QWidget): self.calculateScale() self.padding = 10 self._showKerning = False + self._showMetrics = False + self._verticalFlip = False + self._positions = None + self._selected = None self._wrapLines = True self.scrollArea = scrollArea @@ -231,6 +251,14 @@ class GlyphsCanvas(QWidget): self._showKerning = showKerning self.update() + def setShowMetrics(self, showMetrics): + self._showMetrics = showMetrics + self.update() + + def setVerticalFlip(self, verticalFlip): + self._verticalFlip = verticalFlip + self.update() + def setWrapLines(self, wrapLines): if self._wrapLines == wrapLines: return self._wrapLines = wrapLines @@ -263,28 +291,26 @@ class GlyphsCanvas(QWidget): sh = self.scrollArea.horizontalScrollBar().height() + self.scrollArea.contentsMargins().bottom() self.resize(self.width(), event.size().height() - sh) - # if we have a cell clicked in and we click on the canvas, - # give focus to the canvas in order to quit editing - # TODO: Focus on individual chars and show BBox + active cell (see how rf does active cells) - # QTableWidget.scrollToItem() - def mousePressEvent(self, event): - self.setFocus(Qt.MouseFocusReason) - def wheelEvent(self, event): - # TODO: should it snap to predefined pointSizes? is the scaling factor okay? - # see how rf behaves -> scaling factor grows with sz it seems - decay = event.angleDelta().y() / 120.0 - newPointSize = self.ptSize + int(decay) * 10 - if newPointSize <= 0: return - # TODO: send notification to parent and do all the fuss there - self._pointSizeChanged(newPointSize) - - # TODO: ugh… - comboBox = self.parent().parent().parent().toolbar.comboBox - comboBox.blockSignals(True) - comboBox.setEditText(str(newPointSize)) - comboBox.blockSignals(False) - event.accept() + if event.modifiers() & Qt.ControlModifier: + # TODO: should it snap to predefined pointSizes? is the scaling factor okay? + # see how rf behaves -> scaling factor grows with sz it seems + decay = event.angleDelta().y() / 120.0 + scale = round(self.ptSize / 10) + if scale == 0 and decay >= 0: scale = 1 + newPointSize = self.ptSize + int(decay) * scale + if newPointSize <= 0: return + # TODO: send notification to parent and do all the fuss there + self._pointSizeChanged(newPointSize) + + # TODO: ugh… + comboBox = self.parent().parent().parent().toolbar.comboBox + comboBox.blockSignals(True) + comboBox.setEditText(str(newPointSize)) + comboBox.blockSignals(False) + event.accept() + else: + super(GlyphsCanvas, self).wheelEvent(event) # Tal Leming. Edited. def lookupKerningValue(self, first, second): @@ -326,16 +352,79 @@ class GlyphsCanvas(QWidget): if pair in kerning: return kerning[pair] return 0 + + def mousePressEvent(self, event): + # Take focus to quit eventual cell editing + self.setFocus(Qt.MouseFocusReason) + if event.button() == Qt.LeftButton: + if self._verticalFlip: + baselineShift = -self.descender + else: + baselineShift = self.ascender + found = False + line = (event.y() - self.padding) // (self.ptSize*self._lineHeight) + # XXX: Shouldnt // yield an int? + line = int(line) + if line >= len(self._positions): + self._selected = None + event.accept() + self.update() + return + x = event.x() - self.padding + for index, data in enumerate(self._positions[line]): + pos, width = data + if pos <= x and pos+width > x: + count = 0 + for i in range(line): + count += len(self._positions[i]) + self._selected = count+index + found = True + if not found: self._selected = None + else: self.parent().parent().parent().table.setCurrentColumn(self._selected+1) + event.accept() + self.update() + else: + super(GlyphCanvas, self).mousePressEvent(event) + + def mouseDoubleClickEvent(self, event): + if event.button() == Qt.LeftButton and self._selected is not None: + from fontView import MainWindow + # XXX: we are doing glyph -> name and glyphView does it backwards + # stop adding indirection in ctor + MainWindow._glyphOpened(self, self.glyphs[self._selected].name) + event.accept() + else: + super(GlyphCanvas, self).mouseDoubleClickEvent(event) def paintEvent(self, event): + linePen = QPen(Qt.black) + linePen.setWidth(3) + width = self.width() / self.scale + def paintLineMarks(painter): + painter.save() + painter.scale(self.scale, yDirection*self.scale) + painter.setPen(linePen) + painter.drawLine(0, self.ascender, width, self.ascender) + painter.drawLine(0, 0, width, 0) + painter.drawLine(0, self.descender, width, self.descender) + painter.restore() + painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.fillRect(0, 0, self.width(), self.height(), Qt.white) - painter.translate(self.padding, self.padding+self.ascender*self.scale) + if self._verticalFlip: + baselineShift = -self.descender + yDirection = 1 + else: + baselineShift = self.ascender + yDirection = -1 + painter.translate(self.padding, self.padding+baselineShift*self.scale) # TODO: scale painter here to avoid g*scale everywhere below cur_width = 0 lines = 1 + self._positions = [[]] + if self._showMetrics: paintLineMarks(painter) for index, glyph in enumerate(self.glyphs): # line wrapping # TODO: should padding be added for the right boundary as well? I'd say no but not sure @@ -346,15 +435,24 @@ class GlyphsCanvas(QWidget): else: kern = 0 if self._wrapLines and cur_width + gWidth + kern + self.padding > self.width(): painter.translate(-cur_width, self.ptSize) + if self._showMetrics: paintLineMarks(painter) + self._positions.append([(0, gWidth)]) cur_width = gWidth lines += 1 else: if doKern: painter.translate(kern, 0) + self._positions[-1].append((cur_width, gWidth)) cur_width += gWidth+kern glyphPath = glyph.getRepresentation("defconQt.QPainterPath") painter.save() - painter.scale(self.scale, -self.scale) + painter.scale(self.scale, yDirection*self.scale) + if self._showMetrics: + halfDescent = self.descender/2 + painter.drawLine(0, 0, 0, halfDescent) + painter.drawLine(glyph.width, 0, glyph.width, halfDescent) + if self._selected is not None and index == self._selected: + painter.fillRect(0, self.descender, glyph.width, self.upm, glyphSelectionColor) painter.fillPath(glyphPath, Qt.black) painter.restore() painter.translate(gWidth, 0) @@ -367,7 +465,29 @@ class GlyphsCanvas(QWidget): else: width = self.width() self.resize(width, max(innerHeight, lines*self.ptSize+2*self.padding)) +class SpaceTableWidgetItem(QTableWidgetItem): + def setData(self, role, value): + if role & Qt.EditRole: + # don't set empty or non-number data + if value == "": + return + else: + try: + int(value) + except ValueError: + try: + value = str(round(float(value))) + except ValueError: + return + super(SpaceTableWidgetItem, self).setData(role, value) + class GlyphCellItemDelegate(QStyledItemDelegate): + def createEditor(self, parent, option, index): + editor = super(GlyphCellItemDelegate, self).createEditor(parent, option, index) + #editor.setAlignment(Qt.AlignCenter) + editor.setValidator(QIntValidator(self)) + return editor + # TODO: implement =... lexer def eventFilter(self, editor, event): if event.type() == QEvent.KeyPress: @@ -387,10 +507,7 @@ class GlyphCellItemDelegate(QStyledItemDelegate): chg *= 10 if modifiers & Qt.ControlModifier: chg *= 10 - try: - cur = int(editor.text()) - except ValueError: - cur = float(editor.text()) + cur = int(editor.text()) editor.setText(str(cur+chg)) self.commitData.emit(editor) editor.selectAll() @@ -409,13 +526,13 @@ class SpaceTable(QTableWidget): self.setColumnCount(len(self.glyphs)+2) data = [None, "Width", "Left", "Right"] for index, item in enumerate(data): - cell = QTableWidgetItem(item) + cell = SpaceTableWidgetItem(item) # don't set ItemIsEditable cell.setFlags(Qt.ItemIsEnabled) self.setItem(index, 0, cell) # let's use this one column to compute the width of others - self._cellWidth = .7*self.columnWidth(0) - self.setColumnWidth(0, .6*self.columnWidth(0)) + self._cellWidth = .5*self.columnWidth(0) + self.setColumnWidth(0, self._cellWidth) self.horizontalHeader().hide() self.verticalHeader().hide() @@ -444,10 +561,7 @@ class SpaceTable(QTableWidget): # Glyphs that do not have outlines leave empty cells, can't convert # that to a scalar if not item: return - try: - item = int(item) - except ValueError: - item = float(item) + item = int(item) # -1 because the first col contains descriptive text glyph = self.glyphs[col-1] if row == 1: @@ -465,16 +579,19 @@ class SpaceTable(QTableWidget): margins = self.contentsMargins() height += margins.top() + margins.bottom() return QSize(self.width(), height) + + def setCurrentColumn(self, column): + self.setCurrentCell(0, column) def fillGlyphs(self): def glyphTableWidgetItem(content, blockEdition=False): if content is not None: content = str(content) - item = QTableWidgetItem(content) + item = SpaceTableWidgetItem(content) if content is None or blockEdition: # don't set ItemIsEditable item.setFlags(Qt.ItemIsEnabled) - # TODO: also set alignment during edition - # or leave it as it is now, is fine by me... + # TODO: should fields be centered? I find left-aligned more + # natural to read, personally... #item.setTextAlignment(Qt.AlignCenter) return item |
