Gui

I’m finishing what will hopefully be the last iteration of a gui class. I’m currently considering four approaches:

(1) Gui object accepts all events, and then calls the appropriate object within the widget object in focus.

class Gui:
...
        base.accept('foo', self.bar)
...
    def bar(self):
        self.focus.bar()

(2) Widget objects subclass from DirectObject. Widgets accept the same events, but only execute if they are in focus.

class Widget(DirectObject):
...
        self.accept('foo', self.bar)
...
    def bar(self):
        if gui.focus = self:
        ...

(3) Gui object accepts all events. And then sends an additional event determined by the widget in focus. Widgets listen for these events.

class Gui:
...
        base.accept('foo', self.bar)
...
    def bar(self):
        messenger.send('foo' + self.focus.id)

class Widget:
...
        base.accept('foo' + self.id, self.bar)
...
    def bar(self):
        ...

(4) Widget objects subclass from DirectObject. Gui object calls an onFocus method on the widget in focus that directs the widget to either accept or ignore messages.

class Gui:
...
        self.focus.onFocus()

class Widget(DirectObject):
...
    def onFocus(self):
        self.accept('foo', self.bar)
...
    def onBlur(self):
        self.ignoreAll()

I’m leaning towards (2) or (4) because they make the Gui class much less cluttered. Is there any obvious reason to prefer one approach over the other? (ie. in terms of efficiency, etc.)

Edit: added a fourth option.

tree gui does some thing very simmilar:


class Widget(object):
    """
        This is the root of the UI object hiarchy
    """

    id = None           # name it can be found in the system
    
    parent = None
    x = 0
    y = 0
    width = 20
    height = 20
    _x = 0
    _y = 0
    _width = 20
    _height = 20


    text = None     
    font = "default_font"     
    icon = None

    visable = True       # can we see
    disabled = False     # can we interect   
    control = False      # can we focus and interect    

    
    children = None        # only holders can have children   
    clips = True           # does it clip children 
    antiClips = False      # does it ignore parant clipping      
    
    style = "frame"
    
    editsText = False
    
    color = (1,1,1,1)
    clickExpand = 0
    
    def __init__(self,**placement):
        self.doPlacement(placement)    
        self.children = []
        
    def doPlacement(self, placement):
        
        if "id" in placement: self.id = placement["id"]
        if "x" in placement: self.x = placement["x"]
        if "y" in placement: self.y = placement["y"]
        if "pos" in placement: self.x,self.y = placement["pos"]
        if "width" in placement: self.width = placement["width"]
        if "height" in placement: self.height = placement["height"]
        if "size" in placement: self.width,self.height = placement["size"]
        if "clips" in placement: self.clips = placement["clips"]
        if "style" in placement: self.style = placement["style"]
        if "icon" in placement: self.icon = placement["icon"]
        if "font" in placement: self.font = placement["font"]
        
    def toggle(self):
        self.visable = not self.visable
        
    def show(self):
        self.visable = True
        
    def hide(self):
        self.visable = False
        
    def onAdd(self):
        """ called when this is added to some holder """
        
    def onRemove(self):
        """ called on removal """
        
    def onIn(self):
        """ called when mouse starts to hover """
    onIn = False
        
    def onOut(self):
        """ called when mouse moves out """
    onOut = False
            
    def onHover(self):
        """ called when mouse is hovering over this """
    onHover = False
    
        
    def onClick(self):
        """ called when this is right clicked """
    onClick = False
        
    def onContext(self):
        """ called when this is left clicked """
    onContext = False
        
    def onDoubleClick(self):
        """ called on double right click """
        
    def onFocus(self):
        """ called when this gains focus """
        
    def onUnFocus(self):
        """ called when focus is lost """
        
    def onKey(self, key):
        """ called when key is typed into this """
        
    def onDrag(self):
        """ when dragging """
        
    def onDrop(self):
        """ when the element is dropped """
        
    def mouseEvent(self,event,x,y):
        """ mouse even to override all other mouse events. """
        return False
        
    def fix(self,x,y):
        """ does some thing before the thing is drawn """

Except it does not use direct stuff at all.

Hi zigzag,

I lean towards 3. IMO it sounds more sturdy, more reliable, more “old hunk of metal”, and less “trickster” , “daredevil”, and “seat of pants”.

(Where is my sense of adventure?)