SOLVED Adding text to CurrentGlyphView

  • @gferreira @frederik That was really helpful, thank you!

    If I'm understanding this right, CanvasGroup is a thin layer on top of the glyph view, and we can add whatever vanilla elements to that CanvasGroup?

    Will play around with this. I'm not sure I understand what all of these delegate callbacks do just yet, since sometimes they're not immediately obvious:

    • opaque() — does this need to be specified if shouldDrawBackground() already returns False?

    • acceptsMouseMoved()

    • becomeFirstResponder() & resignFirstResponder() — do these have to be specified if acceptsFirstResponder() already returns False?

    0_1543233080466_Screen Shot 2018-11-26 at 6.50.00 AM.png

  • admin

    It should not be a CanvasGroup, it could also be a vanilla.Group. In this example it shows how to draw something on top of a glyph view disconnected from the zoom level.

    The delegate callbacks are related to a CanvasGroup. for more info see mojo.canvas.CanvasGroup

  • admin

    and if you want to remove the view from the glyph editor: glyphWindow.removeGlyphEditorSubview(view)

  • This post is deleted!

  • Ok, seems that I can just use vanilla.Group to set text, since I don't need to draw anything.

    (I asked earlier about disconnecting from the zoom level, but I assume that's what magnifyWithEvent() is for?)

    Also, will more documentation be added to the page that lists possible delegate methods?

    And one more thing... this is a bit of a side question, but would you ever use a separate object as a delegate?

    from vanilla import *
    from import addObserver, removeObserver
    from mojo.canvas import CanvasGroup
    class OverlayViewController(object):
        def __init__(self):
            addObserver(self, "observerGlyphWindowWillOpen", "glyphWindowWillOpen")
            addObserver(self, "observerGlyphWindowWillClose", "glyphWindowWillClose")
        def observerGlyphWindowWillOpen(self, notification):
            self.window = notification["window"]
            delegateObj = DelegateObj()
            self.view = CanvasGroup((0, -200, -0, -0), delegate=delegateObj)
            self.view.button1 = Button((-130, -40, 120, 22), "Hit Me")
        def observerGlyphWindowWillClose(self, notification):
            removeObserver(self, "glyphWindowWillOpen")
            removeObserver(self, "glyphWindowWillClose")
    class DelegateObj:
        def acceptsFirstResponder(self):
            return False
        def shouldDrawBackground(self):
            return False
        def draw(self):

  • admin

    Each view added with window.addGlyphEditorSubview will be detached from zoom level or panning. The other option is to draw inside the glyph canvas in glyph coordinate space.

    magnifyWithEvent is an event that is called in a Canvas delegate whenever there is a pinch on a trackpad for example.

  • Maybe this comment is unnecessary, but guys,
    I LOVE THIS POST, please add it to the docs, it will be easier to find

  • @RafaŁ-Buchner thanks for the suggestion! here it is

  • Thanks again for this thread and the sample code. I've made a few tools based on it but have run into a problem I can't seem to solve on my own.

    If you open more than one glyph window, either from a second font or the same font, the tool breaks in the older windows. Is there a way to make the sample code work with multiple glyph windows open?

  • admin

    I see, you need to keep a dictionary where the window is the key and the view is the item.

    On glyphWindowWillClose get the window from the notification, remove the view and del the window item in the dictionary.

    Hope this makes sense :)

  • Thanks, Frederik. I couldn't figure that out, but I did figure out I could subclass the vanilla elements. I think this approach will work better for what I'm doing.

    from vanilla import *
    from import addObserver, removeObserver
    from AppKit import NSApp, NSColor, NSTextAlignmentCenter, NSTextAlignmentRight, NSTextAlignmentLeft
    debug = True
    class OverlayViewController(object):
        def __init__(self):
            windowname = 'debug window ui test'
            if debug == True:
                self.w = Window((500, 50), windowname)
                self.w.bind("close", self.windowClose)
                for window in [w for w in NSApp().orderedWindows() if w.isVisible()]:
                    if window.title() == windowname:
            self.view = None
            addObserver(self, 'addToGlyphView', 'glyphWindowWillOpen')
        def windowClose(self, sender):
            print('removing observer')
            removeObserver(self, "glyphWindowWillOpen")
        def addToGlyphView(self, notification):
            self.window = notification["window"]
            x, y, w, h = xywh = (0, 0, -0, 22) 
            this = self.testGV = Group(xywh)
            this.text1 = SubClassedEditText(xywh, '-', window=self.window, sizeStyle='mini', continuous=False)
    class SubClassedEditText(EditText): 
        def __init__(self, *args, **kwargs):
            self.window = kwargs['window']
            del kwargs['window']
            super(SubClassedEditText, self).__init__(*args, **kwargs)
            this = self.getNSTextField()
            addObserver(self, "currentGlyphChanged", "currentGlyphChanged")
        def currentGlyphChanged(self, info):
                g = self.window.getGlyph()
                if g is None: return
                f = g.getParent()
                self.set( + ' '  +
        def _breakCycles(self):
            super(SubClassedEditText, self)._breakCycles()
            removeObserver(self, "currentGlyphChanged")