Observers ↩
Since the release of RoboFont 4.0,
Subscriber
is favored instead of Observers for handling events.Subscriber
is easier to use, less error-prone and it allows event coalescing. It is a great improvement. Observers andmojo.events
will not be technically deprecated – becauseSubscriber
is built on top of them – but we encourage developers to move toSubscriber
!
RoboFont is built around a software design model known as The Observer Pattern:
- a dispatcher sends out notifications when certain events happen
- observers can subscribe and unsubcribe from specific events
There are 3 different types of notifications in RoboFont:
- font data
- defcon notifications
- user interface
- RoboFont notifications
- user interaction
- NSEvent notifications
Observing changes to font data
The base font objects used by RoboFont are provided by defcon. Defcon includes its own object observing system which sends out notifications for changes to the font data.
Here’s a basic example showing how to subscribe to changes to the width of a glyph:
class MyInterface:
def __init__(self, glyph):
self.glyph = glyph
self.glyph.addObserver(self, "glyphWidthChangedCallback", "Glyph.WidthChanged")
def glyphWidthChangedCallback(self, notification):
glyph = notification.object
oldWidth = notification.data['oldValue']
newWidth = notification.data['newValue']
print(f"width of '{glyph.name}' changed! {oldWidth} → {newWidth}")
MyInterface(CurrentGlyph())
All font objects in defcon have addObserver
and removeObserver
methods.
Each font object posts a set of individual notifications about specific kinds of changes. For example, a glyph has separate notifications for changes to width, contours, components, guidelines, anchors, etc.
Use help()
to find out which notifications are posted by each object:
from defcon import Contour
help(Contour)
Help on class Contour in module defcon.objects.contour:
class Contour(defcon.objects.base.BaseObject)
| This object represents a contour and it contains a list of points.
|
| **This object posts the following notifications:**
|
| ===============================
| Name
| ===============================
| Contour.Changed
| Contour.WindingDirectionChanged
| Contour.PointsChanged
| Contour.IdentifierChanged
| ===============================
|
| ...
Observing user interface actions
Font data is edited using the RoboFont interface, which consists of several windows, menus, panels, etc. RoboFont has its own object observing system which sends out notifications for user interface actions.
Here’s a basic example showing how to subscribe to changes in the current glyph:
from mojo.events import addObserver
class MyInterface:
def __init__(self):
addObserver(self, "currentGlyphChangedCallback", "currentGlyphChanged")
def currentGlyphChangedCallback(self, notification):
glyph = notification['glyph']
print("current glyph is '%s'" % glyph.name)
MyInterface()
See RoboFont observers for a list all user interface notifications available.
Use the Event Observer extension to see all interface notifications while you work.