Source

ttgui / tcore.py

Full commit
# -*- coding: utf-8 -*-
import sys
from weakref import WeakSet

from console import debug
from collections import namedtuple



def dispatch(*types):
    context = sys._getframe(1).f_locals
    dispatch_map = context.setdefault("_dispatch_map", {})
    def wrapper(func):
        key = (func.__name__,)
        dispatch_map[key + types] = func
        def inner(self, *args, **kwargs):
            arg_types = tuple([type(a) for a in args])
            real_func = dispatch_map.get(key + arg_types, None)
            if real_func is None:
                raise TypeError("Not method %s with signature %s found" % (func.__name__, str(arg_types)))
            return real_func(self, *args, **kwargs)
        return inner
    return wrapper




class TSize(object):
    __slots__ = ("width", "height")


    @dispatch(int, int)
    def __init__(self, width, height):
        self.width = width
        self.height = height


    def __cmp__(self, other):
        return cmp((self.width, self.height), (other.width, other.height))



class TPoint(object):
    __slots__ = ("x", "y")


    @dispatch(int,int)
    def __init__(self, x, y):
        self.x = x
        self.y = y


    def __cmp__(self, other):
        return cmp((self.x, self.y), (other.x, other.y))


        
        
class TRect(object):
    __slots__ = ("_topLeft", "_size")

    
    
    @dispatch(TPoint, TSize)
    def __init__(self, point, size):
        self._topLeft = point
        self._size = size


    @dispatch(int,int,int,int)
    def __init__(self, x1, y1, width, height):
        self._topLeft = TPoint(x1,y1)
        self._size = TSize(width,height)
    
        
    @property
    def size(self):
        return self._size
    
    
    @property
    def topLeft(self):
        return self._topLeft

        
    @property
    def bottomLeft(self):
        x, y = self.topLeft.x, self.topLeft.y
        return TPoint(x + self.width, y + self.height)


    @property
    def width(self):
        return self._size.width
    
    
    @property
    def height(self):
        return self._size.height

    
    @property
    def left(seft):
        return self._topLeft.x

    
    @property
    def top(self):
        return self._topLeft.y


    def inner(self, radius=1):
        tl = self._topLeft
        sz = self._size
        return TRect(
           TPoint(tl.x+radius, tl.y+radius), 
           TSize(sz.width-1-radius, sz.height-1-radius))



class TEvent(object):

    
    def __init__(self, kind):
        self.kind = kind
        self.accepted = False
        self.ignored = False

    
    def accept(self):
        self.accepted = True
    
    
    def ignore(self):
        self.ignored = True




class TEventLoop(object):
    _instance = None

    def __init__(self):
        self.queue = []


    @classmethod
    def instance(cls):
        if not cls._instance:
            cls._instance = cls()
        return cls._instance


    def postEvent(self, obj, event):
        self.queue.insert(0, (obj, event))


    def processEvent(self):
        if self.queue:
            obj, event = self.queue.pop()
            debug("processing event", event, "for", obj)
            if obj:
                obj.event(event)
            return True
        return False


    


    


class ObjectSignal(object):


    def __init__(self, sender):
        self.sender = sender
        self.slots = WeakSet()
        
        
    def connect(self, slot):
        self.slots.add(slot)
        
        
    def emit(self, *args):
        if self.sender.signalsBlocked():
            return
        TObject._sender = self.sender
        for ref in self.slots:
            slot = ref()
            if slot:
                slot(*args)
        # Object.sender = None



class Signal(object):
    

    def __get__(self, obj, cls):
        signals = obj.__dict__.setdefault("__signals__", {})
        objsig = signals.get(self)
        if not objsig:
            objsig = ObjectSignal(obj)
            signals[self] = objsig
        return objsig





class TObject(object):
    _object_instances = WeakSet()
    
    _sender = None


    destroyed = Signal()



    def __init__(self, parent=None):
        TObject._object_instances.add(self)
        self._children = set()
        self._parent = None
        self._event_filters = set()
        self._signals_blocked = False
    
        if parent:
            self.setParent(parent)        
    
            

    @classmethod
    def sender(cls):
        return cls._sender
    

    
    def signalsBlocked(self):
        return self._signals_blocked
    
    
    def blockSignals(self, flag):
        self._signals_blcoked = flag


    def delete(self):
        self.setParent(None)
        for child in self.children():
            child.delete()
        self.destoyed.emit(self)            
        TObject._object_instances.remove(self)
        
        
    __del__ = delete


    def _add_child(self, child):
        old_parent = child.parent()
        if old_parent:
            old_parent._remove_child(child)
        self._children.add(child)
        child._parent = self
        
        
    def _remove_child(self, child):
        self._children.remove(child)
        child._parent = None
        
            
    def setParent(self, new_parent):
        if not new_parent:
            old_parent = self.parent()
            if old_parent:
                old_parent._remove_child(self)
        else:
            new_parent._add_child(self)

            
    def children(self):
        return list(self._children)
    
    
    def parent(self):
        return self._parent
    
    
    def dump_object_tree(self):
        def dump(obj, level=0):
            print " " * (level*2), obj
            for child in obj.children():
                dump(child, level+1)
        dump(self)

    
    def installEventFilter(self, receiver_object):
        self._event_filters.add(receiver_object)


    def postEvent(self, event):
        TEventLoop.instance().postEvent(self, event)


    def event(self, event):
        for receiver_object in self._event_filters:
            if receiver_object.eventFilter(self, event):
                return

    
    def eventFilter(self, obj, event):
        pass
    


    
if __name__ == "__main__":
    @dispatch(int)
    def test(v):
        print v, "is int"
        
    @dispatch(float)
    def test(v):
        print v, "is float"
        

    test(1)
    test(1.0)