Custom Space Center preview ↩
This example shows how to draw something into the glyphs of a Space Center preview.
The script simply draws a rectangle at each glyph’s bounding box. Whenever a glyph is changed, its preview is updated automatically.
Important in this example is the use of representations to create and cache shapes – this approach is recommended for better performance.
from vanilla import FloatingWindow, CheckBox
from defconAppKit.windows.baseWindow import BaseWindowController
from mojo.events import addObserver, removeObserver
from mojo.UI import CurrentSpaceCenter
from defcon import Glyph, registerRepresentationFactory, unregisterRepresentationFactory
import mojo.drawingTools as ctx
from fontTools.pens.cocoaPen import CocoaPen
def BoundsRectFactory(glyph):
'''A factory function which creates a representation for a given glyph.'''
pen = CocoaPen(glyph.layer)
if not glyph.bounds:
return
x, y, w, h = glyph.bounds
pen.moveTo((x, y))
pen.lineTo((w, y))
pen.lineTo((w, h))
pen.lineTo((x, h))
pen.closePath()
return pen.path
class BoundsRectViewer(BaseWindowController):
'''A simple floating window to toggle the preview on/off.'''
def __init__(self):
self.w = FloatingWindow((123, 40))
self.w.preview = CheckBox((10, 10, -10, 20), 'preview', value=True, callback=self.updatePreviewCallback)
self.setUpBaseWindowBehavior()
# register the representation factory in the defcon Glyph object
registerRepresentationFactory(Glyph, "BoundsRectPreview", BoundsRectFactory)
# add an observer for drawing in the Space Center
addObserver(self, "drawBoundsRect", "spaceCenterDraw")
self.w.open()
def windowCloseCallback(self, sender):
'''Clear observer & representation factory when window is closed.'''
super().windowCloseCallback(sender)
removeObserver(self, "spaceCenterDraw")
unregisterRepresentationFactory(Glyph, "BoundsRectPreview")
def updatePreviewCallback(self, sender):
S = CurrentSpaceCenter()
if not S:
return
S.updateGlyphLineView()
def drawBoundsRect(self, notification):
'''Drawing the bounding box around each glyph.'''
S = CurrentSpaceCenter()
if not S or not self.w.preview.get():
return
# get the current glyph
glyph = notification['glyph']
# get representation for glyph
boundsRect = glyph.getRepresentation("BoundsRectPreview")
if not boundsRect:
return
# draw representation
scale = notification['scale']
ctx.save()
ctx.fill(None)
ctx.strokeWidth(3 * scale)
ctx.stroke(0, 1, 0, 0.5)
ctx.drawPath(boundsRect)
ctx.restore()
BoundsRectViewer()