Changeset 2119

Show
Ignore:
Timestamp:
09/12/07 04:29:27 (1 year ago)
Author:
arj..@yirdis.nl
Message:

Make Element.connect/disconnect/notify no longer needed for associations to work. Associations are now implicitly bi-directional. If not defined, a stub object will be created.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gaphor/trunk/gaphor/UML/properties.py

    r2091 r2119  
    222222        self.composite = composite 
    223223        self.opposite = opposite and intern(opposite) 
     224        self.stub = None 
    224225 
    225226    def load(self, obj, value): 
     
    315316        # Callbacks are only connected if a new relationship has 
    316317        # been established. 
    317         value.connect('__unlink__', self.__on_unlink, obj) 
     318#        value.connect('__unlink__', self.__on_unlink, obj) 
    318319#        if self.composite: 
    319320#            obj.connect('__unlink__', self.__on_composite_unlink, value) 
    320321         
    321322        if not from_opposite and self.opposite: 
    322             getattr(type(value), self.opposite)._set(value, obj, from_opposite=True, do_notify=do_notify) 
     323            opposite = getattr(type(value), self.opposite) 
     324            if not opposite.opposite: 
     325                opposite.stub = self 
     326            opposite._set(value, obj, from_opposite=True, do_notify=do_notify) 
     327        elif not self.opposite: 
     328            if not self.stub: 
     329                self.stub = associationstub(self) 
     330                setattr(self.type, 'UML_associationstub_%x' % id(self), self.stub) 
     331            self.stub._set(value, obj) 
    323332 
    324333        if do_notify: 
     
    342351        if not from_opposite and self.opposite: 
    343352            getattr(type(value), self.opposite)._del(value, obj, from_opposite=True) 
     353        elif not self.opposite: 
     354            if self.stub: 
     355                self.stub._del(value, obj, from_opposite=True) 
    344356 
    345357        event = None 
     
    368380                    event = AssociationSetEvent(obj, self, value, None) 
    369381 
    370         value.disconnect(self.__on_unlink, obj) 
     382#        value.disconnect(self.__on_unlink, obj) 
    371383#        if self.composite: 
    372384#            obj.disconnect(self.__on_composite_unlink, value) 
     
    384396            for value in list(values): 
    385397                # TODO: make normal unlinking work through this method. 
    386                 #self.__delete__(obj, value) 
     398                self.__delete__(obj, value) 
    387399                if composite: 
    388400                    value.unlink() 
    389401 
    390     def __on_unlink(self, value, pspec, obj): 
    391         """ 
    392         Disconnect when the element on the other end of the association 
    393         (value) sends the '__unlink__' signal. This is especially important 
    394         for uni-directional associations. 
    395         """ 
    396         #print '__on_unlink', name, obj, value 
    397         if pspec == '__unlink__': 
    398             self.__delete__(obj, value) 
    399             # re-establish unlink handler: 
    400             value.connect('__unlink__', self.__on_unlink, obj) 
     402#    def __on_unlink(self, value, pspec, obj): 
     403#        """ 
     404#        Disconnect when the element on the other end of the association 
     405#        (value) sends the '__unlink__' signal. This is especially important 
     406#        for uni-directional associations. 
     407#        """ 
     408#        #print '__on_unlink', name, obj, value 
     409#        if pspec == '__unlink__': 
     410#            self.__delete__(obj, value) 
     411#            # re-establish unlink handler: 
     412#            value.connect('__unlink__', self.__on_unlink, obj) 
     413
     414 
     415class AssociationStubError(Exception): 
     416    pass 
     417 
     418 
     419class associationstub(umlproperty): 
     420 
     421    def __init__(self, association): 
     422        self.association = association 
     423        self._name = intern('_stub_%x' % id(self)) 
     424 
     425    def __get__(self, obj, class_=None): 
     426        if obj: 
     427            raise AssociationStubError, 'getting values not allowed' 
     428        return self 
     429 
     430    def __set__(self, obj, value): 
     431        raise AssociationStubError, 'setting values not allowed' 
     432 
     433    def __delete__(self, obj, value=None): 
     434        raise AssociationStubError, 'deleting values not allowed' 
     435 
     436    def save(self, obj, save_func): 
     437        pass 
     438 
     439    def load(self, obj, value): 
     440        pass 
     441 
     442    def unlink(self, obj): 
     443        try: 
     444            values = getattr(obj, self._name) 
     445        except AttributeError: 
     446            pass 
     447        else: 
     448            for value in set(values): 
     449                self.association.__delete__(value, obj) 
     450 
     451    def _set(self, obj, value): 
     452        try: 
     453            getattr(obj, self._name).add(value) 
     454        except AttributeError: 
     455            setattr(obj, self._name, set([value])) 
     456             
     457    def _del(self, obj, value, from_opposite=False): 
     458        getattr(obj, self._name).discard(value) 
    401459 
    402460