first attempt at Subscriber + Merz



  • goede morgen RoboFont,

    I’ve made a first attempt at rewriting a simple move tool in RF4 with Subscriber and Merz – see the current code here.

    Screen Shot 2021-10-10 at 06.50.13.png

    it sort of works, but there are still some glitches and several questions about the right way of doing things in RF4:

    which notifications to use?

    I understand the principle of fine granularity in Subscriber notifications, and that we should subscribe only to changes we really need. the trouble is, there are a lot of notifications now, and it’s not clear to me which one to choose. in this particular example, which one(s) would be the most appropriate? glyphDidChange or glyphDidChangeOutline or currentGlyphDidChange or glyphEditorGlyphDidChange or ...?

    OpenWindow vs. registerGlyphEditorSubscriber

    the tool in this example opens a floating window and subscribes to events.

    in RF3, the window was opened with OpenWindow(MyTool), and the subscription was made inside the __init__ method of that class using addObserver.

    in RF4 we need to use registerGlyphEditorSubscriber(MyTool) to subscribe to the events.

    • if the Glyph Editor is open, calling registerGlyphEditorSubscriber will also open the tool window (?)
    • if the Glyph Editor is not open, the tool window will only be opened later when the Glyph Editor is opened

    questions:

    • is OpenWindow still needed?
    • how can I open the tool window independently of the Glyph Editor being open?

    (I see that WurstSchreiber uses both registerGlyphEditorSubscriber and OpenWindow, with logic split across different objects. does this simple move tool need to follow the same pattern? as you can see I am bit confused :)

    disappearing preview (fixed)

    if I switch to an empty layer, the preview is not shown (as expected). however when I switch back to a layer with contours, the expected preview is no longer displayed. my guess is that calling container.clearSublayers() is breaking something. what would be the proper way of handling this? → fixed by hiding the layers using setVisible(False) instead of deleting them

    disappearing preview when delta is 0 (fixed)

    this is a funny one: if one of the delta values is zero, the preview disappears. it comes back again as soon as the value is changed. → the problem fixed itself somehow

    glyphs with components (fixed)

    when switching to a glyph with components, the following error is thrown:

    Observer '<__main__.MoveGlyphsDialog object at 0x115238d90>' with '_glyphEditorDidSetGlyphInternalCallback' failed: 'NoneType' object is not subscriptable
    Traceback (most recent call last):
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/defcon/objects/component.py", line 183, in drawPoints
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/fontTools/pens/pointPen.py", line 246, in addComponent
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/fontTools/pens/basePen.py", line 191, in addComponent
    TypeError: 'NoneType' object is not subscriptable
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "lib/eventTools/eventManager.pyc", line 165, in callObserver_withMethod_forEvent_withInfo_
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/mojo/subscriber.py", line 1723, in _glyphEditorDidSetGlyphInternalCallback
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/mojo/subscriber.py", line 1636, in _roboFontCallback
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/mojo/subscriber.py", line 3245, in start
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/mojo/subscriber.py", line 3261, in fire
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/mojo/subscriber.py", line 1651, in _roboFontCoalescerCallback
      File "move_RF4.py", line 101, in glyphEditorDidSetGlyph
      File "move_RF4.py", line 133, in _drawBackground
      File "lib/fontObjects/fontPartsWrappers.pyc", line 256, in getRepresentation
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/defcon/objects/base.py", line 342, in getRepresentation
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/merz/tools/cgPen.py", line 114, in glyphCGPathFactory
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/defcon/objects/component.py", line 176, in draw
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/defcon/objects/component.py", line 185, in drawPoints
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/fontTools/pens/pointPen.py", line 246, in addComponent
      File "/Applications/RoboFont4.app/Contents/Resources/lib/python3.7/fontTools/pens/basePen.py", line 191, in addComponent
    TypeError: 'NoneType' object is not subscriptable
    

    what is the correct way to handle this in RF4? do we need to use the DecomposePen to get the path, or is there already a Merz representation for that? → fixed by using the DecomoposePen


    I hope this example is useful for others too. thanks in advance for any tips and corrections!

    happy Sunday hacking to all



  • The glyph edit window preview lives in it's own layer. Here is an example (from this tool https://gist.github.com/okay-type/e8e608926dcbcef6148cfaadddb2e959):

    self.previewContainer = self.glyphEditor.extensionContainer(
                identifier='com.robofont.drawNeighbors.preview',
                location='preview',
                clear=True
            )
    

    Dealing with components continues to be annoying. That tool also uses a DecompPen.



  • hi @okaytype, thanks for the example – I’ve learned a few new things!

    I realize now that the terminology I’ve used above is confusing – what I referred to as ‘preview’ is actually the background layer in Merz (the red letter in the screenshot). I’ll add the preview layer next.


  • admin

    OpenWindow just checks if a class has already an open window or not and brings it back to front. This is not part of subscriber. This is handy incase a users calls the same script twice: you dont want to pop up twice the same control window.

    The example of a tool where you have a palette window and some data to draw in a glyph editor is a frequent pattern.

    • open you control window subscriber
    • register a glyph editor subscriber
    • register some callbacks where you can speak from your control window to any subscriber who wants to listen (see)

    In the cause of Wurschreiber this happens in the same file, maybe not the best solution... we didnt wanted to rewrite to much of the old script to port it to subscriber and merz.

    For the component issue: I guess you are starting from an orphan glyph where the layer is None.

    disappearing preview when delta is 0

    what kind of delta are you speaking of?

    good luck!



  • he @frederik thanks for the pointers, it’s working pretty well now – see the updated gist.

    still trying to understand the part about initialization of window and observers, and how to use registerSubscriberEvent etc. – so the panel can also be opened without the Glyph Editor.

    I will ammend my post above with some answers. any suggestions on how to improve the code are welcome! cheers


Log in to reply