Subscribing to RoboFont application events ↩
This example shows a floating window that displays a list of all open fonts. The window knows when the user has changed the open fonts (opened, closed, created a new one) and updates accordingly.
The tool subscribes to font info and features. It uses the merz
module to draw a little graph in the “glyph” panel.
import vanilla
import merz
from mojo.subscriber import Subscriber, WindowController, registerRoboFontSubscriber
from mojo.roboFont import AllFonts
WHITE = (1, 1, 1, 1)
class RoboFontWithUISubscriberDemo(Subscriber, WindowController):
debug = True
def build(self):
self.fontList = []
self.w = vanilla.FloatingWindow((0, 500), "RoboFont Useless Data")
columnDescriptions = [
dict(title="name")
]
self.fontList = vanilla.List(
"auto",
[],
columnDescriptions=columnDescriptions,
showColumnTitles=False,
allowsEmptySelection=False,
allowsMultipleSelection=False,
selectionCallback=self.fontListSelectionCallback
)
self.infoList = vanilla.List(
"auto",
[]
)
self.featureList = vanilla.List(
"auto",
[]
)
self.namesView = merz.MerzView(
"auto",
backgroundColor=(0, 0, 0, 1)
)
columnDescriptions = [
dict(
width=300
),
{},
{},
dict(
width=100
),
]
rows = [
dict(
height=25,
cells=(
vanilla.TextBox("auto", "Fonts:"),
vanilla.TextBox("auto", "Info:"),
vanilla.TextBox("auto", "Features:"),
vanilla.TextBox("auto", "Glyphs:"),
)
),
dict(
height=400,
cells=(
self.fontList,
self.infoList,
self.featureList,
self.namesView
),
),
]
self.w.gridView = vanilla.GridView(
"auto",
rows,
columnDescriptions=columnDescriptions,
columnWidth=150,
columnSpacing=10,
rowHeight=25,
rowSpacing=0
)
metrics = dict(
margin=15
)
rules = [
"H:|-margin-[gridView]-margin-|",
"V:|-margin-[gridView]-margin-|"
]
self.w.addAutoPosSizeRules(rules, metrics)
def started(self):
for font in AllFonts():
self.fontList.append(
dict(
name=f"{font.info.familyName}-{font.info.styleName}",
font=font
)
)
self.w.open()
# ---- callbacks with delays ---- #
fontDocumentDidOpenNewDelay = 0
def fontDocumentDidOpenNew(self, info):
font = info["font"]
self.fontList.append(
dict(
name="New Family-New Style",
font=font
)
)
fontDocumentDidOpenDelay = 0
def fontDocumentDidOpen(self, info):
font = info["font"]
self.fontList.append(
dict(
name=f"{font.info.familyName}-{font.info.styleName}",
font=font
)
)
fontDocumentWillCloseDelay = 0
def fontDocumentWillClose(self, info):
font = info["font"]
for i, item in enumerate(self.fontList.get()):
if item["font"] == font:
break
del self.fontList[i]
def fontListSelectionCallback(self, sender):
selection = sender.getSelection()
if not selection:
font = None
else:
font = sender[selection[0]]["font"]
self.updateInfoList(font)
self.updateFeatureList(font)
self.updateNamesView(font)
# ---- update functions ---- #
def updateInfoList(self, font):
items = []
if font is not None:
text = []
if font.info.copyright is not None:
text.append(font.info.copyright)
if font.info.trademark is not None:
text.append(font.info.trademark)
if font.info.license is not None:
text.append(font.info.license)
text = "\n".join(text)
if text:
items = text.replace("\n", " ").split(" ")
items = [i for i in items if i]
items.sort()
self.infoList.set(items)
def updateFeatureList(self, font):
items = []
if font is not None:
text = font.features.text
if text:
items = text.replace("\n", " ").split(" ")
items = [i for i in items if i]
items.sort()
self.featureList.set(items)
def updateNamesView(self, font):
if font is None:
names = []
else:
names = font.glyphOrder
view = self.namesView
container = view.getMerzContainer()
container.clearSublayers()
if not names:
return
lengths = [len(name) for name in names]
minLength = min(lengths)
maxLength = max(lengths)
xSteps = maxLength - minLength
ySteps = len(names)
width = view.width()
height = view.height()
offset = 10
if xSteps == 0:
xStep = 0
else:
xStep = (width - (offset * 2)) / xSteps
yStep = (height - (offset * 2)) / ySteps
pathLayer = container.appendPathSublayer(
fillColor=None,
strokeColor=WHITE,
strokeWidth=1
)
pen = pathLayer.getPen()
pen.moveTo((offset, offset))
y = offset
for length in lengths:
x = offset + (xStep * length)
pen.lineTo((x, y))
y += yStep
pen.endPath()
registerRoboFontSubscriber(RoboFontWithUISubscriberDemo)