Changeset 1112

Show
Ignore:
Timestamp:
12/18/06 13:35:32 (2 years ago)
Author:
arjanmol
Message:
  • got combined join/fork and decision/merge nodes working
  • updated testset
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gaphor/branches/new-canvas/gaphor/adapters/connectors.py

    r1111 r1112  
    409409        return connected_items 
    410410 
    411     def connect_subject(self): 
     411    def connect_subject(self, handle): 
    412412        """ 
    413413        Establish the relationship at model level. 
     
    435435            opposite = self.line.opposite(handle) 
    436436            if opposite.connected_to: 
    437                 self.connect_subject(
     437                self.connect_subject(handle
    438438                line = self.line 
    439439                if line.subject: 
     
    491491        return super(DependencyConnect, self).glue(handle, x, y) 
    492492 
    493     def connect_subject(self): 
     493    def connect_subject(self, handle): 
    494494        """ 
    495495        TODO: cleck for existing relationships (use self.relation()) 
     
    549549        return super(ImplementationConnect, self).glue(handle, x, y) 
    550550 
    551     def connect_subject(self): 
     551    def connect_subject(self, handle): 
    552552        relation = self.relationship_or_new(UML.Implementation, 
    553553                    ('contract', None), 
     
    587587        return super(GeneralizationConnect, self).glue(handle, x, y) 
    588588 
    589     def connect_subject(self): 
     589    def connect_subject(self, handle): 
    590590        relation = self.relationship_or_new(UML.Generalization, 
    591591                    ('general', None), 
     
    627627        return super(IncludeConnect, self).glue(handle, x, y) 
    628628 
    629     def connect_subject(self): 
     629    def connect_subject(self, handle): 
    630630        relation = self.relationship_or_new(UML.Include, 
    631631                    ('addition', None), 
     
    667667        return super(ExtendConnect, self).glue(handle, x, y) 
    668668 
    669     def connect_subject(self): 
     669    def connect_subject(self, handle): 
    670670        relation = self.relationship_or_new(UML.Extend, 
    671671                    ('extendedCase', None), 
     
    714714        return super(ExtensionConnect, self).glue(handle, x, y) 
    715715 
    716     def connect_subject(self): 
     716    def connect_subject(self, handle): 
    717717        element = self.element 
    718718        line = self.line 
     
    811811        return super(AssociationConnect, self).glue(handle, x, y) 
    812812 
    813     def connect_subject(self): 
     813    def connect_subject(self, handle): 
    814814        element = self.element 
    815815        line = self.line 
     
    931931        return super(FlowConnect, self).glue(handle, x, y) 
    932932 
    933     def connect_subject(self): 
     933    def connect_subject(self, handle): 
    934934        line = self.line 
    935935        element = self.element 
     
    947947        if not relation.guard: 
    948948            relation.guard = UML.create(UML.LiteralSpecification) 
    949         self.line.subject = relation 
     949        line.subject = relation 
     950        opposite = line.opposite(handle) 
     951        if opposite and isinstance(opposite.connected_to, (items.ForkNodeItem, items.DecisionNodeItem)): 
     952            adapter = component.queryMultiAdapter((opposite.connected_to, line), IConnect) 
     953            adapter.combine_nodes() 
     954 
     955    def disconnect_subject(self, handle): 
     956        super(FlowConnect, self).disconnect_subject(handle) 
     957        line = self.line 
     958        opposite = line.opposite(handle) 
     959        if opposite and isinstance(opposite.connected_to, (items.ForkNodeItem, items.DecisionNodeItem)): 
     960            adapter = component.queryMultiAdapter((opposite.connected_to, line), IConnect) 
     961            adapter.decombine_nodes() 
    950962 
    951963component.provideAdapter(factory=FlowConnect, 
     
    10031015        line = self.line 
    10041016        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() 
    1063  
    1064         # Switch class for self.element Join/Fork depending on the number 
    1065         # of incoming/outgoing edges. 
    1066         element = self.element 
    10671017        subject = element.subject 
    10681018        if len(subject.incoming) > 1 and len(subject.outgoing) < 2: 
     
    10721022            UML.swap_element(subject, fork_node_class) 
    10731023            element.request_update() 
    1074         elif len(subject.incoming) > 1 and len(subject.outgoing) > 1: 
    1075             self.combine_nodes(fork_node_class, join_node_class) 
    1076  
    1077     def disconnect_subject(self, fork_node_class=None, join_node_class=None): 
     1024        elif not element.combined and len(subject.incoming) > 1 and len(subject.outgoing) > 1: 
     1025            join_node = subject 
     1026 
     1027            # determine flow class: 
     1028            if [ f for f in join_node.incoming if isinstance(f, UML.ObjectFlow) ]: 
     1029                flow_class = UML.ObjectFlow 
     1030            else: 
     1031                flow_class = UML.ControlFlow 
     1032             
     1033            UML.swap_element(join_node, join_node_class) 
     1034            fork_node = UML.create(fork_node_class) 
     1035            for flow in list(join_node.outgoing): 
     1036                flow.source = fork_node 
     1037            flow = UML.create(flow_class) 
     1038            flow.source = join_node 
     1039            flow.target = fork_node 
     1040 
     1041            element.combined = fork_node 
     1042 
     1043    def decombine_nodes(self, fork_node_class, join_node_class): 
     1044        """ 
     1045        Decombine join/fork or decision/merge nodes. 
     1046        """ 
     1047        line = self.line 
     1048        element = self.element 
     1049        if element.combined: 
     1050            join_node = element.subject 
     1051            flow = join_node.outgoing[0] 
     1052            fork_node = flow.target 
     1053            assert fork_node is element.combined 
     1054            assert isinstance(join_node, join_node_class) 
     1055            assert isinstance(fork_node, fork_node_class) 
     1056 
     1057            if len(join_node.incoming) < 2 or len(fork_node.outgoing) < 2: 
     1058                # Move all outgoing edges to the first node (the join node): 
     1059                for flow in list(fork_node.outgoing): 
     1060                    flow.source = join_node 
     1061                flow.unlink() 
     1062                fork_node.unlink() 
     1063 
     1064                # swap subject to fork node if outgoing > 1 
     1065                if len(join_node.outgoing) > 1: 
     1066                    assert len(join_node.incoming) < 2 
     1067                    UML.swap_element(join_node, fork_node_class) 
     1068                element.combined = None 
     1069 
     1070    def connect_subject(self, handle): 
     1071        """ 
     1072        In addition to a subject connect, the subject of the element may  
     1073        be changed. 
     1074        For readability, parameters are named afther the classes used by 
     1075        Join/Fork nodes. 
     1076        """ 
     1077        super(FlowForkDecisionNodeConnect, self).connect_subject(handle) 
     1078 
     1079        # Switch class for self.element Join/Fork depending on the number 
     1080        # of incoming/outgoing edges. 
     1081        self.combine_nodes() 
     1082 
     1083    def disconnect_subject(self): 
    10781084        super(FlowForkDecisionNodeConnect, self).disconnect_subject() 
    10791085        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. 
     1086            self.decombine_nodes() 
    10831087 
    10841088 
     
    10891093    component.adapts(items.ForkNodeItem, items.FlowItem) 
    10901094 
    1091     def connect_subject(self): 
    1092         super(FlowForkNodeConnect, self).connect_subject(join_node_class=UML.JoinNode, fork_node_class=UML.ForkNode) 
     1095    def combine_nodes(self, fork_node_class=UML.ForkNode, 
     1096                      join_node_class=UML.JoinNode): 
     1097        super(FlowForkNodeConnect, self).combine_nodes(fork_node_class=fork_node_class, join_node_class=join_node_class) 
     1098 
     1099    def decombine_nodes(self, fork_node_class=UML.ForkNode, 
     1100                        join_node_class=UML.JoinNode): 
     1101        super(FlowForkNodeConnect, self).decombine_nodes(fork_node_class=fork_node_class, join_node_class=join_node_class) 
    10931102 
    10941103component.provideAdapter(FlowForkNodeConnect) 
     
    11011110    component.adapts(items.DecisionNodeItem, items.FlowItem) 
    11021111 
    1103     def connect_subject(self): 
    1104         super(FlowDecisionNodeConnect, self).connect_subject(join_node_class=UML.MergeNode, fork_node_class=UML.DecisionNode) 
     1112    def combine_nodes(self, fork_node_class=UML.DecisionNode, 
     1113                      join_node_class=UML.MergeNode): 
     1114        super(FlowDecisionNodeConnect, self).combine_nodes(fork_node_class=fork_node_class, join_node_class=join_node_class) 
     1115 
     1116    def decombine_nodes(self, fork_node_class=UML.DecisionNode, 
     1117                        join_node_class=UML.MergeNode): 
     1118        super(FlowDecisionNodeConnect, self).decombine_nodes(fork_node_class=fork_node_class, join_node_class=join_node_class) 
    11051119 
    11061120component.provideAdapter(FlowDecisionNodeConnect) 
  • gaphor/branches/new-canvas/gaphor/adapters/tests/test_connector.py

    r1109 r1112  
    611611        a2 = diagram.create(items.ActionItem, subject=UML.create(UML.Action)) 
    612612        a3 = diagram.create(items.ActionItem, subject=UML.create(UML.Action)) 
     613        a4 = diagram.create(items.ActionItem, subject=UML.create(UML.Action)) 
    613614        f1 = diagram.create(itemClass, subject=UML.create(joinNodeClass)) 
    614615 
     
    617618        # Connect between two actions (ControlFlow) 
    618619        # Connecting line this: 
    619         #                  |--flow2-->[ a2 ] 
     620        #        head  tail|--flow2-->[ a2 ] 
    620621        # [ a1 ] --flow1-->| 
    621622        #                  |--flow3-->[ a3 ] 
     
    653654        assert flow2.subject in f1.subject.outgoing 
    654655        assert type(f1.subject) is joinNodeClass 
     656        assert flow2.canvas 
    655657 
    656658        adapter = component.queryMultiAdapter((f1, flow3), IConnect) 
     
    660662        assert flow3.subject.source is f1.subject 
    661663        assert flow3.subject in f1.subject.outgoing 
     664        assert len(f1.subject.outgoing) == 2 
    662665 
    663666        assert type(f1.subject) is forkNodeClass, f1.subject 
    664667 
    665         # flow4 can't be an incoming flow
     668        # flow4 will force the forknode to become a combined node
    666669 
    667670        adapter = component.queryMultiAdapter((f1, flow4), IConnect) 
    668671        assert adapter 
    669672        adapter.connect(flow4.tail, flow4.tail.x, flow4.tail.y) 
    670         assert flow4.tail.connected_to is None 
     673        assert type(f1.subject) is forkNodeClass 
     674 
     675        adapter = component.queryMultiAdapter((a4, flow4), IConnect) 
     676        adapter.connect(flow4.head, flow4.head.x, flow4.head.y) 
     677        assert type(f1.subject) is joinNodeClass 
     678        assert f1.combined 
     679        assert flow4.tail.connected_to is f1 
     680        assert flow4.subject.target is f1.subject 
     681        assert type(f1.combined) is forkNodeClass, f1.combined 
     682        assert flow1.subject in f1.subject.incoming 
     683        assert flow4.subject in f1.subject.incoming 
     684        assert flow2.subject in f1.combined.outgoing, f1.combined.outgoing 
     685        assert flow3.subject in f1.combined.outgoing, f1.combined.outgoing 
     686        assert len(f1.subject.outgoing) == 1 
     687        assert len(f1.combined.incoming) == 1 
     688        assert f1.subject.outgoing[0] is f1.combined.incoming[0] 
    671689 
    672690        # flow4 can be connected as outgoing flow though: 
    673  
    674         adapter = component.queryMultiAdapter((f1, flow4), IConnect) 
    675         assert adapter 
    676         adapter.connect(flow4.head, flow4.head.x, flow4.head.y) 
    677         assert flow4.head.connected_to is f1 
     691        #adapter = component.queryMultiAdapter((f1, flow4), IConnect) 
     692        #assert adapter 
     693        #adapter.connect(flow4.head, flow4.head.x, flow4.head.y) 
     694        #assert flow4.head.connected_to is f1 
    678695 
    679696        adapter.disconnect(flow4.head) 
    680697        assert flow4.head.connected_to is None 
     698        adapter = component.queryMultiAdapter((f1, flow4), IConnect) 
     699        adapter.disconnect(flow4.tail) 
     700        assert not f1.combined 
     701         
     702        assert flow2.canvas 
     703        assert flow2.canvas.solver 
    681704 
    682705        # Now change the ForkNode back into a JoinNode by moving flow2 
     
    711734 
    712735        # And of course I can't add another outgoing edge: 
    713         adapter = component.queryMultiAdapter((f1, flow4), IConnect) 
    714         assert adapter 
    715         adapter.connect(flow4.head, flow4.head.x, flow4.head.y) 
    716         assert flow4.head.connected_to is None 
     736        #adapter = component.queryMultiAdapter((f1, flow4), IConnect) 
     737        #assert adapter 
     738        #adapter.connect(flow4.head, flow4.head.x, flow4.head.y) 
     739        #assert flow4.head.connected_to is None 
    717740 
    718741 
  • gaphor/branches/new-canvas/gaphor/diagram/activitynodes.py

    r1111 r1112  
    133133 
    134134    def _set_combined(self, value): 
    135         self.preserve_property('combined') 
     135        #self.preserve_property('combined') 
    136136        self._combined = value 
    137137