a button inside subview



  • Hi, I have a general question. I don't understand, why the button's callback doesn't work. Can I have a working button inside subview, please? Thanks

    from vanilla import *
    from mojo.events import addObserver, removeObserver
    from mojo.UI import CurrentGlyphWindow
    from mojo.events import addObserver, clearObservers
    
    class DrawObserverExample:
        def __init__(self):
            clearObservers()
            addObserver(self, "drawSub", "drawPreview")
            try:
                window = CurrentGlyphWindow()
                view = Group((0, 0, -0, 50))
                view.button = Button((0, 0, 100, 10), 'hi', callback=self.changeTitle)
                view.text = EditText((0, 20, 100, 30))
                view.button.setTitle('testje')
                window.addGlyphEditorSubview(view)
            except Exception as e:
                print(e)
        
        def changeTitle(self, event):
            print(event)
    
        def drawSub(self, notification):
            print(notification)
    
    DrawObserverExample()
    

  • admin

    hello @jansindl3r,

    if you wish to add vanilla objects to the Glyph View, it’s easier to start from the Glyph Editor subview example. the buttons are added when the glyph window is opened by observing the glyphWindowWillOpen event; the drawing is handled separately by observing draw events.

    ps. don’t use clearObservers(), as it will invalidate all other observers (see the docs). use removeObserver instead.



  • Hi @gferreira, Thanks! I use clearObservers only when debugging, I am aware of that. It is handy for that, though sometimes buggy code is still listening to the actions and throwing errors so I need to restart robofont, is there a way how to do it without restarting the app? Has it happened to you as well?
    I don't understand connection between the callback and the functions at all, sorry :( Is it described anywhere? I tried to search.


  • admin

    hi @jansindl3r,

    is there a way how to do it without restarting the app?

    yes: you can open/close a vanilla window to add/remove the observers.

    here’s a simpler ‘button inside subview’ example, I hope this is clearer:

    Screen Shot 2019-10-08 at 19.56.58.png

    from random import random
    from vanilla import FloatingWindow, Button
    import mojo.drawingTools as ctx
    from mojo.events import addObserver, removeObserver
    from mojo.canvas import CanvasGroup
    from mojo.UI import CurrentGlyphWindow, UpdateCurrentGlyphView
    
    class OverlayViewExample(object):
    
        color = 1, 0, 0, 0.5
    
        def __init__(self):
            ### for debugging only
            self.w = FloatingWindow((150, 50), "debug only")
            self.w.bind("close", self.windowClose)
            self.w.open()
            ### 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"]
            self.view = CanvasGroup((0, -200, -0, -0), delegate=self)
            self.view.button = Button((-130, -50, 120, 22), "Hit Me", callback=self.buttonCallback)
            self.window.addGlyphEditorSubview(self.view)
    
        def observerDraw(self, notification):
            if self.view:
                self.view.show(True)
    
        def observerDrawPreview(self, notification):
            # hide the view in Preview mode
            if self.view:
                self.view.show(False)
    
        # button callback
    
        def buttonCallback(self, sender):
            print('button pressed')
            self.color = random(), random(), random(), 0.5
            UpdateCurrentGlyphView()
    
        # 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
    
        # draw callback
    
        def draw(self):
            g = self.window.getGlyph()
            if g is None:
                return
            x, y, w, h = self.window.getVisibleRect()
            ctx.fill(*self.color)
            ctx.rect(x + 10, y + 10, 100, 100)
    
    OverlayViewExample()
    

    ps.

    I don't understand connection between the callback and the functions at all, sorry :( Is it described anywhere? I tried to search.

    not sure if this is what you mean, but the canvas delegate callbacks are inherited from the wrapped NSView object. see the introduction in Canvas and CanvasGroup