This example shows how to draw or add controls directly into the Glyph Editor.

from vanilla import *
import mojo.drawingTools as ctx
from import addObserver, removeObserver
from mojo.canvas import CanvasGroup
from mojo.UI import CurrentGlyphWindow

class OverlayViewController(object):

    def __init__(self):
        ### for debugging only
        self.w = FloatingWindow((150, 50), "debug only")
        self.w.bind("close", self.windowClose)
        ### end debugging
        self.view = None
        addObserver(self, "observerGlyphWindowWillOpen", "glyphWindowWillOpen")
        addObserver(self, "observerDraw", "draw")
        addObserver(self, "observerDrawPreview", "drawPreview")

    def windowClose(self, sender):
        removeObserver(self, "glyphWindowWillOpen")
        removeObserver(self, "draw")
        removeObserver(self, "drawPreview")

    def observerGlyphWindowWillOpen(self, notification):
        self.window = notification["window"]
        # create a view with some controls
        self.view = CanvasGroup((0, -200, -0, -0), delegate=self)
        self.view.button1 = Button((-130, -40, 120, 22), "Hit Me", callback=self.button1Callback)
        self.view.button2 = Button((-260, -40, 120, 22), "Show Controls", callback=self.button2Callback)
        self.view.list = List((-260, 10, -10, -50), ["a", "b", "c", "Do SomeThing"])
        # add the view to the GlyphEditor

    def observerDraw(self, notification):
        if self.view:

    def observerDrawPreview(self, notification):
        # hide the view in Preview mode
        if self.view:

    # button callbacks

    def button1Callback(self, sender):
        print('button 1 pressed')

    def button2Callback(self, sender):
        print('button 2 pressed')

    # canvas delegate callbacks

    def opaque(self):
        return True

    def acceptsFirstResponder(self):
        return False

    def acceptsMouseMoved(self):
        return True

    def becomeFirstResponder(self):
        return False

    def resignFirstResponder(self):
        return False

    def shouldDrawBackground(self):
        return False

    def draw(self):
        g = self.window.getGlyph()
        if g is None:

        f = g.getParent()
        x, y, w, h = self.window.getVisibleRect()
        h = self.view.height() - y

        # draw a rect around the view area
        ctx.stroke(0, 1, 0)
        ctx.rect(x+5, y+5, w-10, h-10)

        # draw some preview glyphs
        testGlyphs = ["n", "o"]
        glyphs = []
        for c in testGlyphs:
            if c in f:

        ctx.translate(50, 150)
        for glyph in glyphs:
            ctx.translate(glyph.width, 0)

Last edited on 12/12/2019