Shared UI widget code design question

Here’s a really minimal example. MGui does more of this, including multicast delegates and pymel-style dot access to properties, but this is a cheap way to make extensible widgets:


class Widget(object):
    CMD = cmds.control
    
    def __init__(self, *args, **kwargs):
        self.widget = self.CMD(*args, **kwargs)
       
    def set(self, **kw):
        flags = {'e': True}
        flags.update(**kw)
        self.CMD(self.widget, **flags)

    def get(self, **kw):
        flags = {'q': True}
        flags.update(**kw)
        self.CMD(self.widget, **flags)
        
        
    def __repr__(self):
        return self.widget
        
class Button(Widget):
    CMD = cmds.button
    
    def __init__(self, *args, **kwargs):
        super(Button, self).__init__(*args, **kwargs)
        self.set(command = self.clicked)
        
    def clicked(*_):
        print "clicked"
        
class OtherButton(Button):
    
    def clicked(self, *_):
        super(OtherButton, self).clicked(*_)
        print "and did other stuff on", self
    
w = cmds.window()
c = cmds.columnLayout()
b = Button("button")
b2 = OtherButton("special button")
cmds.showWindow(w)

if you wanted to call the functionality from outside you could just do “b2.clicked()” although that’s bad practice. If “I can click or I can call” is the goal, then:


class Button(Widget):
    CMD = cmds.button
    
    def __init__(self, *args, **kwargs):
        super(Button, self).__init__(*args, **kwargs)
        self.set(command = self.clicked)
        self.execute = lambda ignore: None
        
        
    def clicked(self, *_):
        print "clicked"

You can replace execute with some other function that does the hard work but can be managed independently: for example you could tack this on to the end:


b2.execute = lambda x: cmds.polyCube()

would make button to create a cube, but you could split the ‘execute’ functionality from the pure UI stuff by calling execute in preference to clicked. And obviously it could be more elaborate than a dumb lambda. I usually make handlers pass themselves in so it’s easy to write generic handlers that can tell which widget called them