Changeset 1111

Show
Ignore:
Timestamp:
12/18/06 00:47:55 (2 years ago)
Author:
arjanmol
Message:

implemented combined node items

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gaphor/branches/new-canvas/gaphor/UML/elementfactory.py

    r1109 r1111  
    166166        if element.__class__ is not new_class: 
    167167            element.__class__ = new_class 
    168             self.notify(element, '__class__') 
     168            element.notify('__class__') 
    169169 
    170170    def connect(self, callback, *data): 
  • gaphor/branches/new-canvas/gaphor/adapters/connectors.py

    r1109 r1111  
    934934        line = self.line 
    935935        element = self.element 
     936        # TODO: connect opposite side again (in case it's a join/fork or 
     937        #       decision/merge node) 
    936938        if isinstance(line.head.connected_to, items.ObjectNodeItem) \ 
    937939           or isinstance(line.tail.connected_to, items.ObjectNodeItem): 
     
    955957 
    956958 
    957 class FlowForkNodeConnect(FlowConnect): 
    958     """ 
    959     Connect Flow to a ForkNode 
    960     """ 
    961     component.adapts(items.ForkNodeItem, items.FlowItem) 
     959class FlowForkDecisionNodeConnect(FlowConnect): 
     960    """ 
     961    Abstract class with common behaviour for Fork/Join node and 
     962    Decision/Merge node. 
     963    """ 
    962964 
    963965    def glue(self, handle, x, y): 
     
    984986        # If one side of self.element has more than one edge, the 
    985987        # type of node is determined (either join or fork). 
    986         if handle is line.head and len(subject.incoming) > 1 and len(subject.outgoing) > 0: 
    987             return None 
    988  
    989         if handle is line.tail and len(subject.incoming) > 0 and len(subject.outgoing) > 1: 
    990             return None 
    991  
    992         return super(FlowForkNodeConnect, self).glue(handle, x, y) 
    993  
    994     def connect_subject(self): 
    995         super(FlowForkNodeConnect, self).connect_subject() 
     988        # 
     989        # TODO: remove these restrictions and create a combined join/fork or 
     990        #       decision/merge node  
     991        #if handle is line.head and len(subject.incoming) > 1 and len(subject.outgoing) > 0: 
     992        #    return None 
     993        # 
     994        #if handle is line.tail and len(subject.incoming) > 0 and len(subject.outgoing) > 1: 
     995        #    return None 
     996 
     997        return super(FlowForkDecisionNodeConnect, self).glue(handle, x, y) 
     998 
     999    def combine_nodes(self, fork_node_class, join_node_class): 
     1000        """ 
     1001        Combine join/fork or decision/methe nodes into one diagram item. 
     1002        """ 
     1003        line = self.line 
     1004        element = self.element 
     1005        join_node = element.subject 
     1006        if element.combined: 
     1007            return 
     1008 
     1009        # determine flow class: 
     1010        if [ f for f in join_node.incoming if isinstance(f, UML.ObjectFlow) ]: 
     1011            flow_class = UML.ObjectFlow 
     1012        else: 
     1013            flow_class = UML.ControlFlow 
     1014         
     1015        UML.swap_element(join_node, join_node_class) 
     1016        fork_node = UML.create(UML.ForkNode) 
     1017        for flow in join_node.outgoing: 
     1018            flow.source = fork_node 
     1019        flow = UML.create(flow_class) 
     1020        flow.source = join_node 
     1021        flow.target = fork_node 
     1022 
     1023        element.combined = fork_node 
     1024 
     1025    def decombine_nodes(self, fork_node_class, join_node_class): 
     1026        """ 
     1027        Decombine join/fork or decision/merge nodes. 
     1028        """ 
     1029        line = self.line 
     1030        element = self.element 
     1031        if element.combined: 
     1032            join_node = element.subject 
     1033            flow = subject.outgoing[0] 
     1034            fork_node = flow.target 
     1035            assert fork_node is element.combined 
     1036            assert isinstance(join_node, join_node_class) 
     1037            assert isinstance(fork_node, fork_node_class) 
     1038 
     1039            if len(join_node.incoming) < 2 or len(fork_node.outgoing) < 2: 
     1040                # Move all outgoing edges to the first node (the join node): 
     1041                for flow in fork_node.outgoing: 
     1042                    flow.source = join_node 
     1043                flow.unlink() 
     1044                fork_node.unlink() 
     1045 
     1046                # swap subject to fork node if outgoing > 1 
     1047                if len(subject.outgoing) > 1: 
     1048                    assert len(subject.incoming) < 2 
     1049                    UML.swap_element(subject, fork_node_class) 
     1050            else: 
     1051                # Illegal state! 
     1052                pass 
     1053            element.combined = None 
     1054 
     1055    def connect_subject(self, fork_node_class, join_node_class): 
     1056        """ 
     1057        In addition to a subject connect, the subject of the element may  
     1058        be changed. 
     1059        For readability, parameters are named afther the classes used by 
     1060        Join/Fork nodes. 
     1061        """ 
     1062        super(FlowForkDecisionNodeConnect, self).connect_subject() 
    9961063 
    9971064        # Switch class for self.element Join/Fork depending on the number 
    9981065        # of incoming/outgoing edges. 
    999         subject = self.element.subject 
     1066        element = self.element 
     1067        subject = element.subject 
    10001068        if len(subject.incoming) > 1 and len(subject.outgoing) < 2: 
    1001             UML.swap_element(subject, UML.JoinNode) 
     1069            UML.swap_element(subject, join_node_class) 
     1070            element.request_update() 
    10021071        elif len(subject.incoming) < 2 and len(subject.outgoing) > 1: 
    1003             UML.swap_element(subject, UML.ForkNode) 
     1072            UML.swap_element(subject, fork_node_class) 
     1073            element.request_update() 
    10041074        elif len(subject.incoming) > 1 and len(subject.outgoing) > 1: 
    1005             raise RuntimeError, 'Inconsistent state' 
     1075            self.combine_nodes(fork_node_class, join_node_class) 
     1076 
     1077    def disconnect_subject(self, fork_node_class=None, join_node_class=None): 
     1078        super(FlowForkDecisionNodeConnect, self).disconnect_subject() 
     1079        if self.element.combined: 
     1080            self.decombine_nodes(fork_node_class, join_node_class) 
     1081        # TODO: if combined node: un-combine if only one incoming or outgoing 
     1082        #       egde on one side. 
     1083 
     1084 
     1085class FlowForkNodeConnect(FlowForkDecisionNodeConnect): 
     1086    """ 
     1087    Connect Flow to a ForkNode 
     1088    """ 
     1089    component.adapts(items.ForkNodeItem, items.FlowItem) 
     1090 
     1091    def connect_subject(self): 
     1092        super(FlowForkNodeConnect, self).connect_subject(join_node_class=UML.JoinNode, fork_node_class=UML.ForkNode) 
    10061093 
    10071094component.provideAdapter(FlowForkNodeConnect) 
    10081095 
    10091096 
    1010 class FlowDecisionNodeConnect(FlowConnect): 
    1011     """ 
    1012     Connect Flow to a ForkNode 
     1097class FlowDecisionNodeConnect(FlowForkDecisionNodeConnect): 
     1098    """ 
     1099    Connect Flow to a DecisionNode 
    10131100    """ 
    10141101    component.adapts(items.DecisionNodeItem, items.FlowItem) 
    10151102 
    1016     def glue(self, handle, x, y): 
    1017         """ 
    1018         In addition to the normal check, one end should have at most one 
    1019         edge (incoming or outgoing). 
    1020         """ 
    1021         opposite = self.line.opposite(handle) 
    1022         line = self.line 
    1023         element = self.element 
    1024         subject = element.subject 
    1025         connected_to = opposite.connected_to 
    1026  
    1027         # Element can not connect back to itself 
    1028         if connected_to is element: 
    1029             return None 
    1030  
    1031         # Same goes for subjects: 
    1032         if connected_to and \ 
    1033                 (not (connected_to.subject or element.subject)) \ 
    1034                  and connected_to.subject is element.subject: 
    1035             return None 
    1036  
    1037         # If one side of self.element has more than one edge, the 
    1038         # type of node is determined (either join or fork). 
    1039         if handle is line.head and len(subject.incoming) > 1 and len(subject.outgoing) > 0: 
    1040             return None 
    1041  
    1042         if handle is line.tail and len(subject.incoming) > 0 and len(subject.outgoing) > 1: 
    1043             return None 
    1044  
    1045         return super(FlowDecisionNodeConnect, self).glue(handle, x, y) 
    1046  
    10471103    def connect_subject(self): 
    1048         super(FlowDecisionNodeConnect, self).connect_subject() 
    1049  
    1050         # Switch class for self.element Join/Fork depending on the number 
    1051         # of incoming/outgoing edges. 
    1052         subject = self.element.subject 
    1053         if len(subject.incoming) > 1 and len(subject.outgoing) < 2: 
    1054             UML.swap_element(subject, UML.MergeNode) 
    1055         elif len(subject.incoming) < 2 and len(subject.outgoing) > 1: 
    1056             UML.swap_element(subject, UML.DecisionNode) 
    1057         elif len(subject.incoming) > 1 and len(subject.outgoing) > 1: 
    1058             raise RuntimeError, 'Inconsistent state' 
     1104        super(FlowDecisionNodeConnect, self).connect_subject(join_node_class=UML.MergeNode, fork_node_class=UML.DecisionNode) 
    10591105 
    10601106component.provideAdapter(FlowDecisionNodeConnect) 
  • gaphor/branches/new-canvas/gaphor/diagram/activitynodes.py

    r1110 r1111  
    119119 
    120120 
    121 class FDNode(ActivityNodeItem): 
     121class ForkDecisionNodeItem(ActivityNodeItem): 
    122122    """ 
    123123    Abstract class for fork and decision UI nodes. These nodes contain 
     
    129129    def __init__(self, id=None): 
    130130        ActivityNodeItem.__init__(self, id) 
    131         self._combined = Fals
     131        self._combined = Non
    132132        self.set_prop_persistent('combined') 
    133133 
    134  
    135     def do_set_property(self, pspec, value): 
    136         if pspec.name == 'combined': 
    137             self.preserve_property('combined') 
    138             self._combined = value 
    139         else: 
    140             ActivityNodeItem.do_set_property(self, pspec, value) 
    141  
    142  
    143     def do_get_property(self, pspec): 
    144         if pspec.name == 'combined': 
    145             return self._combined 
    146         else: 
    147             return ActivityNodeItem.do_get_property(self, pspec) 
    148  
    149  
    150  
    151 class DecisionNodeItem(FDNode): 
     134    def _set_combined(self, value): 
     135        self.preserve_property('combined') 
     136        self._combined = value 
     137 
     138    combined = property(lambda s: s._combined, _set_combined) 
     139         
     140 
     141class DecisionNodeItem(ForkDecisionNodeItem): 
    152142    """ 
    153143    Representation of decision or merge node. 
     
    181171 
    182172 
    183 class ForkNodeItem(FDNode): 
     173class ForkNodeItem(ForkDecisionNodeItem): 
    184174    """ 
    185175    Representation of fork and join node. 
     
    193183 
    194184    def __init__(self, id=None): 
    195         FDNode.__init__(self, id) 
     185        ForkDecisionNodeItem.__init__(self, id) 
    196186 
    197187        self._join_spec = 'join spec test' 
     
    238228        text element. 
    239229        """ 
    240         FDNode.on_subject_notify(self, pspec, notifiers) 
     230        ForkDecisionNodeItem.on_subject_notify(self, pspec, notifiers) 
    241231        if self.subject and isinstance(self.subject, UML.JoinNode): 
    242232            if not self.subject.joinSpec: 
  • gaphor/branches/new-canvas/gaphor/diagram/diagramitem.py

    r1087 r1111  
    200200        # save persistent properties 
    201201        for p in self._persistent_props: 
    202             save_func(p, getattr(self, p.replace('-', '_'))
     202            save_func(p, getattr(self, p.replace('-', '_')), reference=True
    203203 
    204204 
  • gaphor/branches/new-canvas/gaphor/diagram/flow.py

    r1104 r1111  
    445445    if is_fd(node): 
    446446        source = target 
    447         move_collection(node, source, 'incoming') 
     447        move_collection(node, target, 'incoming') 
    448448 
    449449        # create new fork node 
    450         cls = node_classes[source.__class__] 
     450        cls = node_classes[target.__class__] 
    451451        log.debug('creating %s' % cls) 
    452452        target = factory.create(cls) 
     
    454454    else: 
    455455        # fork node is created, referenced by target 
    456         move_collection(source, target, 'outgoing') 
     456        move_collection(node, target, 'outgoing') 
    457457 
    458458    assert not is_fd(source)