Changeset 1087
- Timestamp:
- 11/23/06 00:31:59 (2 years ago)
- Files:
-
- gaphor/branches/new-canvas/TODO (modified) (1 diff)
- gaphor/branches/new-canvas/gaphor/actions/itemactions.py (modified) (16 diffs)
- gaphor/branches/new-canvas/gaphor/adapters/connectors.py (modified) (14 diffs)
- gaphor/branches/new-canvas/gaphor/adapters/tests/test_connector.py (modified) (2 diffs)
- gaphor/branches/new-canvas/gaphor/diagram/association.py (modified) (17 diffs)
- gaphor/branches/new-canvas/gaphor/diagram/diagramitem.py (modified) (6 diffs)
- gaphor/branches/new-canvas/gaphor/misc/ipair.py (modified) (1 diff)
- gaphor/branches/new-canvas/gaphor/ui/namespace.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
gaphor/branches/new-canvas/TODO
r1056 r1087 6 6 - split DiagramItem in a stereotype support, SubjectSupport and some 7 7 other support classes. 8 9 - Currently (r1085) relations (association, dependency) can be created between 10 model elements. Some items (e.g. comment lines) can be connected to the 11 relationship at the time it realizes a relation at model level (both ends 12 get connected). This should result in a trigger to the attached 13 (comment-)line so it can also establish it's relationship at model level. 14 This can be solved in two places: 15 1. handle it in the DiagramItem. This will ensure such relationship is 16 always up to date, but may result in weird behavior in the loading code. 17 2. handle it in the IConnect adapters. That's the only place where 18 relationship are established so doing some extra work there won't hurt 19 Hmm.. Option 2 I guess.. 8 20 9 21 - using stereotypes gaphor/branches/new-canvas/gaphor/actions/itemactions.py
r1070 r1087 497 497 498 498 def get_association_end(self): 499 return get _parent_focus_item(self._window).get_property(self.end_name)499 return getattr(get_parent_focus_item(self._window), self.end_name) 500 500 501 501 def update(self): … … 503 503 item = get_parent_focus_item(self._window) 504 504 if isinstance(item, items.AssociationItem): 505 end = item.get_property(self.end_name)505 end = getattr(item, self.end_name) 506 506 if end.subject: 507 507 self.active = (end.get_navigability() == self.navigable) … … 520 520 id = 'Head_isNavigable' 521 521 label = 'Navigable' 522 end_name = 'head' 522 end_name = 'head_end' 523 group = 'head_navigable' 523 524 navigable = True 524 525 … … 529 530 id = 'Head_isNotNavigable' 530 531 label = 'Non-Navigable' 531 end_name = 'head' 532 end_name = 'head_end' 533 group = 'head_navigable' 532 534 navigable = False 533 535 … … 538 540 id = 'Head_unknownNavigation' 539 541 label = 'Unknown' 540 end_name = 'head' 542 end_name = 'head_end' 543 group = 'head_navigable' 541 544 navigable = None 542 545 … … 547 550 id = 'Tail_isNavigable' 548 551 label = 'Navigable' 549 end_name = 'tail' 552 end_name = 'tail_end' 553 group = 'tail_navigable' 550 554 navigable = True 551 555 … … 556 560 id = 'Tail_isNotNavigable' 557 561 label = 'Non-Navigable' 558 end_name = 'tail' 562 end_name = 'tail_end' 563 group = 'tail_navigable' 559 564 navigable = False 560 565 … … 565 570 id = 'Tail_unknownNavigation' 566 571 label = 'Unknown' 567 end_name = 'tail' 572 end_name = 'tail_end' 573 group = 'tail_navigable' 568 574 navigable = None 569 575 … … 579 585 try: 580 586 item = get_parent_focus_item(self._window) 581 if isinstance(item, AssociationItem):582 end = item.get_property(self.end_name)587 if isinstance(item, items.AssociationItem): 588 end = getattr(item, self.end_name) 583 589 if end.subject: 584 590 self.active = (end.subject.aggregation == self.aggregation) … … 589 595 def execute(self): 590 596 if self.active: 591 subject = get _parent_focus_item(self._window).get_property(self.end_name).subject597 subject = getattr(get_parent_focus_item(self._window), self.end_name).subject 592 598 assert isinstance(subject, UML.Property) 593 599 subject.aggregation = self.aggregation … … 598 604 label = 'None' 599 605 group = 'head_aggregation' 600 end_name = 'head '606 end_name = 'head_end' 601 607 aggregation = 'none' 602 608 … … 608 614 label = 'Shared' 609 615 group = 'head_aggregation' 610 end_name = 'head '616 end_name = 'head_end' 611 617 aggregation = 'shared' 612 618 … … 618 624 label = 'Composite' 619 625 group = 'head_aggregation' 620 end_name = 'head '626 end_name = 'head_end' 621 627 aggregation = 'composite' 622 628 … … 628 634 label = 'None' 629 635 group = 'tail_aggregation' 630 end_name = 'tail '636 end_name = 'tail_end' 631 637 aggregation = 'none' 632 638 … … 638 644 label = 'Shared' 639 645 group = 'tail_aggregation' 640 end_name = 'tail '646 end_name = 'tail_end' 641 647 aggregation = 'shared' 642 648 … … 648 654 label = 'Composite' 649 655 group = 'tail_aggregation' 650 end_name = 'tail '656 end_name = 'tail_end' 651 657 aggregation = 'composite' 652 658 gaphor/branches/new-canvas/gaphor/adapters/connectors.py
r1085 r1087 146 146 Base class for connecting two lines to each other. 147 147 The line that is conencted to is called 'element', as in ElementConnect. 148 149 Once a line has been connected at both ends, and a model element is 150 assigned to it, all items connectedt to this line (e.g. Comments) 151 receive a connect() call. This allows already connected lines to set 152 up relationships at model level too. 148 153 """ 149 154 … … 281 286 if super(CommentLineLineConnect, self).connect(handle, x, y): 282 287 opposite = self.line.opposite(handle) 283 if opposite.connected_to :288 if opposite.connected_to and self.element.subject: 284 289 if isinstance(opposite.connected_to.subject, UML.Comment): 285 290 opposite.connected_to.subject.annotatedElement = self.element.subject … … 301 306 class RelationshipConnect(ElementConnect): 302 307 """ 303 Base class for relationship connections, such as Association,308 Base class for relationship connections, such as associations, 304 309 dependencies and implementations. 305 310 … … 374 379 return relation 375 380 381 def trigger_connected_items(self, line): 382 """ 383 Cause items connected to @line to reconnect, allowing them to 384 establish or destroy relationships at model level. 385 """ 386 canvas = line.canvas 387 solver = canvas.solver 388 389 # First make sure coordinates match 390 solver.solve() 391 for item, handle in self.line.canvas.get_connected_items(line): 392 adapter = component.queryMultiAdapter((line, item), IConnect) 393 assert adapter 394 adapter.connect(handle, handle.x, handle.y) 395 376 396 def glue(self, handle, x, y): 377 397 opposite = self.line.opposite(handle) … … 392 412 return super(RelationshipConnect, self).glue(handle, x, y) 393 413 414 def connect_subject(self): 415 """ 416 Establish the relationship at model level. 417 """ 418 raise NotImplemented, 'Implement connect_subject() in a subclass' 419 420 def connect(self, handle, x, y): 421 """ 422 Connect the items to each other. The model level relationship 423 is created by create_subject() 424 """ 425 if super(RelationshipConnect, self).connect(handle, x, y): 426 opposite = self.line.opposite(handle) 427 if opposite.connected_to: 428 self.connect_subject() 429 line = self.line 430 if line.subject: 431 self.trigger_connected_items(line) 432 394 433 def disconnect(self, handle): 395 434 """ … … 400 439 old = self.line.subject 401 440 del self.line.subject 441 if old: 442 self.trigger_connected_items(self.line) 402 443 if old and len(old.presentation) == 0: 403 444 old.unlink() … … 428 469 return super(DependencyConnect, self).glue(handle, x, y) 429 470 430 def connect (self, handle, x, y):471 def connect_subject(self): 431 472 """ 432 473 TODO: cleck for existing relationships (use self.relation()) 433 474 """ 434 if super(DependencyConnect, self).connect(handle, x, y): 435 dep = self.line 436 opposite = self.line.opposite(handle) 437 if opposite.connected_to: 438 if dep.auto_dependency: 439 dep.set_dependency_type() 440 if dep.dependency_type is UML.Realization: 441 relation = self.relationship_or_new(dep.dependency_type, 442 head=('realizingClassifier', None), 443 tail=('abstraction', 'realization')) 444 else: 445 relation = self.relationship_or_new(dep.dependency_type, 446 ('supplier', 'supplierDependency'), 447 ('client', 'clientDependency')) 448 dep.subject = relation 475 line = self.line 476 if line.auto_dependency: 477 line.set_dependency_type() 478 if line.dependency_type is UML.Realization: 479 relation = self.relationship_or_new(line.dependency_type, 480 head=('realizingClassifier', None), 481 tail=('abstraction', 'realization')) 482 else: 483 relation = self.relationship_or_new(line.dependency_type, 484 ('supplier', 'supplierDependency'), 485 ('client', 'clientDependency')) 486 line.subject = relation 449 487 450 488 component.provideAdapter(DependencyConnect) … … 479 517 return super(ImplementationConnect, self).glue(handle, x, y) 480 518 481 def connect(self, handle, x, y): 482 if super(ImplementationConnect, self).connect(handle, x, y): 483 line = self.line 484 opposite = self.line.opposite(handle) 485 if opposite.connected_to: 486 relation = self.relationship_or_new(UML.Implementation, 487 ('contract', None), 488 ('implementatingClassifier', 'implementation')) 489 line.subject = relation 519 def connect_subject(self): 520 relation = self.relationship_or_new(UML.Implementation, 521 ('contract', None), 522 ('implementatingClassifier', 'implementation')) 523 self.line.subject = relation 490 524 491 525 component.provideAdapter(ImplementationConnect) … … 511 545 # return super(GeneralizationConnect, self).glue(handle, x, y) 512 546 513 def connect(self, handle, x, y): 514 if super(GeneralizationConnect, self).connect(handle, x, y): 515 line = self.line 516 opposite = self.line.opposite(handle) 517 if opposite.connected_to: 518 relation = self.relationship_or_new(UML.Generalization, 519 ('general', None), 520 ('specific', 'generalization')) 521 line.subject = relation 547 def connect_subject(self): 548 relation = self.relationship_or_new(UML.Generalization, 549 ('general', None), 550 ('specific', 'generalization')) 551 self.line.subject = relation 522 552 523 553 component.provideAdapter(GeneralizationConnect) … … 542 572 return super(IncludeConnect, self).glue(handle, x, y) 543 573 544 def connect(self, handle, x, y): 545 if super(IncludeConnect, self).connect(handle, x, y): 546 line = self.line 547 opposite = self.line.opposite(handle) 548 if opposite.connected_to: 549 relation = self.relationship_or_new(UML.Include, 550 ('addition', None), 551 ('includingCase', 'include')) 552 line.subject = relation 574 def connect_subject(self): 575 relation = self.relationship_or_new(UML.Include, 576 ('addition', None), 577 ('includingCase', 'include')) 578 line.subject = relation 553 579 554 580 component.provideAdapter(IncludeConnect) … … 573 599 return super(ExtendConnect, self).glue(handle, x, y) 574 600 575 def connect(self, handle, x, y): 576 if super(ExtendConnect, self).connect(handle, x, y): 577 line = self.line 578 opposite = self.line.opposite(handle) 579 if opposite.connected_to: 580 relation = self.relationship_or_new(UML.Extend, 581 ('extendedCase', None), 582 ('extension', 'extend')) 583 line.subject = relation 601 def connect_subject(self): 602 relation = self.relationship_or_new(UML.Extend, 603 ('extendedCase', None), 604 ('extension', 'extend')) 605 line.subject = relation 584 606 585 607 component.provideAdapter(ExtendConnect) … … 614 636 return super(ExtensionConnect, self).glue(handle, x, y) 615 637 616 def connect(self, handle, x, y): 617 if super(ExtensionConnect, self).connect(handle, x, y): 618 element = self.element 619 line = self.line 620 opposite = self.line.opposite(handle) 621 if opposite.connected_to: 622 c1 = line.head.connected_to 623 c2 = line.tail.connected_to 624 if c1 and c2: 625 head_type = c1.subject 626 tail_type = c2.subject 627 628 # First check if we do not already contain the right subject: 629 if line.subject: 630 end1 = line.subject.memberEnd[0] 631 end2 = line.subject.memberEnd[1] 632 if (end1.type is head_type and end2.type is tail_type) \ 633 or (end2.type is head_type and end1.type is tail_type): 634 return 635 636 # Find all associations and determine if the properties on 637 # the association ends have a type that points to the class. 638 for assoc in UML.select(): 639 if isinstance(assoc, UML.Extension): 640 end1 = assoc.memberEnd[0] 641 end2 = assoc.memberEnd[1] 642 if (end1.type is head_type and end2.type is tail_type) \ 643 or (end2.type is head_type and end1.type is tail_type): 644 # check if this entry is not yet in the diagram 645 # Return if the association is not (yet) on the canvas 646 for item in assoc.presentation: 647 if item.canvas is element.canvas: 648 break 649 else: 650 line.subject = assoc 638 def connect_subject(self): 639 element = self.element 640 line = self.line 641 642 c1 = line.head.connected_to 643 c2 = line.tail.connected_to 644 if c1 and c2: 645 head_type = c1.subject 646 tail_type = c2.subject 647 648 # First check if we do not already contain the right subject: 649 if line.subject: 650 end1 = line.subject.memberEnd[0] 651 end2 = line.subject.memberEnd[1] 652 if (end1.type is head_type and end2.type is tail_type) \ 653 or (end2.type is head_type and end1.type is tail_type): 654 return 655 656 # Find all associations and determine if the properties on 657 # the association ends have a type that points to the class. 658 for assoc in UML.select(): 659 if isinstance(assoc, UML.Extension): 660 end1 = assoc.memberEnd[0] 661 end2 = assoc.memberEnd[1] 662 if (end1.type is head_type and end2.type is tail_type) \ 663 or (end2.type is head_type and end1.type is tail_type): 664 # check if this entry is not yet in the diagram 665 # Return if the association is not (yet) on the canvas 666 for item in assoc.presentation: 667 if item.canvas is element.canvas: 668 break 669 else: 670 line.subject = assoc 651 671 # if (end1.type is head_type and end2.type is tail_type): 652 672 # line.head_subject = end1 … … 655 675 # line.head_subject = end2 656 676 # line.tail_subject = end1 657 return658 else:659 # Create a new Extension relationship660 relation = UML.create(UML.Extension)661 head_end = UML.create(UML.Property)662 tail_end = UML.create(UML.ExtensionEnd)663 relation.package = element.canvas.diagram.namespace664 relation.memberEnd = head_end665 relation.memberEnd = tail_end666 relation.ownedEnd = tail_end667 head_end.type = head_type668 tail_end.type = tail_type669 tail_type.ownedAttribute = head_end670 head_end.name = 'baseClass'671 672 line.subject = relation677 return 678 else: 679 # Create a new Extension relationship 680 relation = UML.create(UML.Extension) 681 head_end = UML.create(UML.Property) 682 tail_end = UML.create(UML.ExtensionEnd) 683 relation.package = element.canvas.diagram.namespace 684 relation.memberEnd = head_end 685 relation.memberEnd = tail_end 686 relation.ownedEnd = tail_end 687 head_end.type = head_type 688 tail_end.type = tail_type 689 tail_type.ownedAttribute = head_end 690 head_end.name = 'baseClass' 691 692 line.subject = relation 673 693 674 694 def disconnect(self, handle): … … 715 735 return super(AssociationConnect, self).glue(handle, x, y) 716 736 717 def connect(self, handle, x, y): 718 if super(AssociationConnect, self).connect(handle, x, y): 719 element = self.element 720 line = self.line 721 opposite = self.line.opposite(handle) 722 if opposite.connected_to: 723 c1 = line.head.connected_to 724 c2 = line.tail.connected_to 725 if c1 and c2: 726 head_type = c1.subject 727 tail_type = c2.subject 728 729 # First check if we do not already contain the right subject: 730 if line.subject: 731 end1 = line.subject.memberEnd[0] 732 end2 = line.subject.memberEnd[1] 733 if (end1.type is head_type and end2.type is tail_type) \ 734 or (end2.type is head_type and end1.type is tail_type): 737 def connect_subject(self): 738 element = self.element 739 line = self.line 740 741 c1 = line.head.connected_to 742 c2 = line.tail.connected_to 743 if c1 and c2: 744 head_type = c1.subject 745 tail_type = c2.subject 746 747 # First check if we do not already contain the right subject: 748 if line.subject: 749 end1 = line.subject.memberEnd[0] 750 end2 = line.subject.memberEnd[1] 751 if (end1.type is head_type and end2.type is tail_type) \ 752 or (end2.type is head_type and end1.type is tail_type): 753 return 754 755 # Find all associations and determine if the properties on 756 # the association ends have a type that points to the class. 757 for assoc in UML.select(): 758 if isinstance(assoc, UML.Association): 759 end1 = assoc.memberEnd[0] 760 end2 = assoc.memberEnd[1] 761 if (end1.type is head_type and end2.type is tail_type) \ 762 or (end2.type is head_type and end1.type is tail_type): 763 # check if this entry is not yet in the diagram 764 # Return if the association is not (yet) on the canvas 765 for item in assoc.presentation: 766 if item.canvas is element.canvas: 767 break 768 else: 769 line.subject = assoc 770 if (end1.type is head_type and end2.type is tail_type): 771 line.head_end.subject = end1 772 line.tail_end.subject = end2 773 else: 774 line.head_end.subject = end2 775 line.tail_end.subject = end1 735 776 return 736 737 # Find all associations and determine if the properties on 738 # the association ends have a type that points to the class. 739 for assoc in UML.select(): 740 if isinstance(assoc, UML.Association): 741 end1 = assoc.memberEnd[0] 742 end2 = assoc.memberEnd[1] 743 if (end1.type is head_type and end2.type is tail_type) \ 744 or (end2.type is head_type and end1.type is tail_type): 745 # check if this entry is not yet in the diagram 746 # Return if the association is not (yet) on the canvas 747 for item in assoc.presentation: 748 if item.canvas is element.canvas: 749 break 750 else: 751 line.subject = assoc 752 if (end1.type is head_type and end2.type is tail_type): 753 line.head_end.subject = end1 754 line.tail_end.subject = end2 755 else: 756 line.head_end.subject = end2 757 line.tail_end.subject = end1 758 return 759 else: 760 # Create a new Extension relationship 761 relation = UML.create(UML.Association) 762 head_end = UML.create(UML.Property) 763 head_end.lowerValue = UML.create(UML.LiteralSpecification) 764 tail_end = UML.create(UML.Property) 765 tail_end.lowerValue = UML.create(UML.LiteralSpecification) 766 relation.package = element.canvas.diagram.namespace 767 relation.memberEnd = head_end 768 relation.memberEnd = tail_end 769 head_end.type = head_type 770 tail_end.type = tail_type 771 head_type.ownedAttribute = head_end 772 tail_type.ownedAttribute = head_end 773 774 line.subject = relation 775 line.head_end.subject = head_end 776 line.tail_end.subject = tail_end 777 else: 778 # Create a new Extension relationship 779 relation = UML.create(UML.Association) 780 head_end = UML.create(UML.Property) 781 head_end.lowerValue = UML.create(UML.LiteralSpecification) 782 tail_end = UML.create(UML.Property) 783 tail_end.lowerValue = UML.create(UML.LiteralSpecification) 784 relation.package = element.canvas.diagram.namespace 785 relation.memberEnd = head_end 786 relation.memberEnd = tail_end 787 head_end.type = head_type 788 tail_end.type = tail_type 789 head_type.ownedAttribute = tail_end 790 tail_type.ownedAttribute = head_end 791 792 line.subject = relation 793 line.head_end.subject = head_end 794 line.tail_end.subject = tail_end 777 795 778 796 def disconnect(self, handle): gaphor/branches/new-canvas/gaphor/adapters/tests/test_connector.py
r1085 r1087 150 150 assert assoc.subject in comment.subject.annotatedElement, comment.subject.annotatedElement 151 151 152 # Disconnect actor:152 # Disconnect comment: 153 153 154 154 adapter.disconnect(handle) … … 158 158 assert len(comment.subject.annotatedElement) == 0, comment.subject.annotatedElement 159 159 assert not assoc.subject in comment.subject.annotatedElement, comment.subject.annotatedElement 160 161 # Connect again: 162 163 adapter.connect(handle, handle.x, handle.y) 164 assert handle.connected_to is not None, handle.connected_to 165 166 167 def test_connector_association_connect(self): 168 """ 169 Test behaviour when the CommentLine's subject (association) is 170 connected after the comment line is connected. 171 """ 172 diagram = UML.create(UML.Diagram) 173 comment = diagram.create(items.CommentItem, subject=UML.create(UML.Comment)) 174 line = diagram.create(items.CommentLineItem) 175 line.head.pos = 100, 100 176 line.tail.pos = 100, 100 177 c1 = diagram.create(items.ClassItem, subject=UML.create(UML.Class)) 178 c2 = diagram.create(items.ClassItem, subject=UML.create(UML.Class)) 179 assoc = diagram.create(items.AssociationItem) 180 181 # connect the comment 182 183 adapter = component.queryMultiAdapter((comment, line), IConnect) 184 185 handle = line.tail 186 adapter.connect(handle, handle.x, handle.y) 187 188 assert handle.connected_to is comment 189 assert handle._connect_constraint is not None 190 assert len(comment.subject.annotatedElement) == 0, comment.subject.annotatedElement 191 192 # connect opposite end to the association: 193 194 adapter = component.queryMultiAdapter((assoc, line), IConnect) 195 handle = line.head 196 adapter.connect(handle, handle.x, handle.y) 197 198 assert handle.connected_to is assoc 199 assert handle._connect_constraint is not None 200 assert len(comment.subject.annotatedElement) == 0, comment.subject.annotatedElement 201 assert assoc.subject is None 202 203 # Now connect the association to the classes: 204 205 adapter = component.queryMultiAdapter((c1, assoc), IConnect) 206 handle = assoc.head 207 adapter.connect(handle, handle.x, handle.y) 208 209 assert handle.connected_to is c1 210 assert handle._connect_constraint is not None 211 assert len(comment.subject.annotatedElement) == 0, comment.subject.annotatedElement 212 assert assoc.subject is None 213 214 adapter = component.queryMultiAdapter((c2, assoc), IConnect) 215 handle = assoc.tail 216 adapter.connect(handle, handle.x, handle.y) 217 218 assert assoc.head.connected_to is c1 219 assert assoc.tail.connected_to is c2 220 assert assoc.subject 221 assert len(comment.subject.annotatedElement) == 1, comment.subject.annotatedElement 222 assert assoc.subject in comment.subject.annotatedElement 223 224 # And now disconnect again: 225 226 adapter.disconnect(handle) 227 assert assoc.tail.connected_to is None 228 assert assoc.subject is None 229 assert comment.subject is not None 230 assert len(comment.subject.annotatedElement) == 0, comment.subject.annotatedElement 231 232 # TODO: add test 233 # What happens when an association is displayed in two diagrams and 234 # the comment is connected in one diagram. That assoc. is broken. 160 235 161 236 gaphor/branches/new-canvas/gaphor/diagram/association.py
r1077 r1087 24 24 from gaphor.undomanager import undoable 25 25 #from gaphor.diagram import Relationship 26 from gaphor.diagram.diagramitem import DiagramItem26 from gaphor.diagram.diagramitem import SubjectSupport 27 27 from gaphor.diagram.diagramline import DiagramLine 28 28 … … 74 74 'AssociationInvertDirection', 75 75 'separator', 76 # 'Side _A', ( 77 # 'Head_isNavigable', 78 # 'separator', 79 # 'Head_AggregationNone', 80 # 'Head_AggregationShared', 81 # 'Head_AggregationComposite'), 82 # 'Side _B', ( 83 # 'Tail_isNavigable', 84 # 'separator', 85 # 'Tail_AggregationNone', 86 # 'Tail_AggregationShared', 87 # 'Tail_AggregationComposite') 76 'Head', ( 77 'Head_unknownNavigation', 78 'Head_isNotNavigable', 79 'Head_isNavigable', 80 'separator', 81 'Head_AggregationNone', 82 'Head_AggregationShared', 83 'Head_AggregationComposite'), 84 'Tail', ( 85 'Tail_unknownNavigation', 86 'Tail_isNotNavigable', 87 'Tail_isNavigable', 88 'separator', 89 'Tail_AggregationNone', 90 'Tail_AggregationShared', 91 'Tail_AggregationComposite'), 88 92 ) 89 93 … … 141 145 self._tail_end.postload() 142 146 143 # def do_set_property(self, pspec, value):144 # if pspec.name == 'head-subject':145 # self._head_end.subject = value146 # elif pspec.name == 'tail-subject':147 # self._tail_end.subject = value148 # elif pspec.name == 'show-direction':149 # self.preserve_property('show-direction')150 # self._show_direction = value151 # self.request_update()152 # else:153 # DiagramLine.do_set_property(self, pspec, value)154 155 # def do_get_property(self, pspec):156 # if pspec.name == 'head':157 # return self._head_end158 # if pspec.name == 'tail':159 # return self._tail_end160 # elif pspec.name == 'head-subject':161 # return self._head_end.subject162 # elif pspec.name == 'tail-subject':163 # return self._tail_end.subject164 # elif pspec.name == 'show-direction':165 # return self._show_direction166 # else:167 # return DiagramLine.do_get_property(self, pspec)168 169 147 head_end = property(lambda self: self._head_end) 170 148 … … 224 202 225 203 def update(self, context): 226 """Update the shapes and sub-items of the association.""" 204 """ 205 Update the shapes and sub-items of the association. 206 """ 227 207 228 208 handles = self.handles() … … 240 220 elif self._head_end.get_navigability(): 241 221 self.draw_head = self.draw_head_navigable 242 if self._head_end.get_navigability() == False:222 elif self._head_end.get_navigability() == False: 243 223 self.draw_head = self.draw_head_none 244 224 else: … … 250 230 self.draw_tail = self.draw_tail_shared 251 231 elif self._tail_end.get_navigability(): 252 # This side is navigable: 253 self.draw_tail = draw_tail_navigable 232 self.draw_tail = self.draw_tail_navigable 254 233 elif self._tail_end.get_navigability() == False: 255 self.draw_tail = draw_tail_none234 self.draw_tail = self.draw_tail_none 256 235 else: 257 236 self.draw_tail = self.draw_tail_undefined … … 305 284 cr = context.cairo 306 285 cr.line_to(0, 0) 307 cr.move_to( -14, -4)286 cr.move_to(6, -4) 308 287 cr.rel_line_to(8, 8) 309 288 cr.rel_move_to(0, -8) … … 321 300 """ 322 301 self.draw_tail_shared(context) 323 context.cairo.fill_preserve() 302 cr = context.cairo 303 cr.fill_preserve() 324 304 cr.stroke() 325 305 … … 338 318 """ 339 319 cr = context.cairo 340 cr.line_to( -20, 0)341 cr.stroke()342 cr.line_to( -10, -6)320 cr.line_to(20, 0) 321 #cr.stroke() 322 cr.line_to(10, -6) 343 323 cr.line_to(0, 0) 344 cr.line_to( -10, 6)345 cr.line_to( -20, 0)324 cr.line_to(10, 6) 325 cr.line_to(20, 0) 346 326 347 327 def draw_head_navigable(self, context): … … 360 340 cr = context.cairo 361 341 cr.line_to(0, 0) 362 cr.move_to( -15, -6)342 cr.move_to(15, -6) 363 343 cr.line_to(0, 0) 364 cr.line_to( -15, 6)344 cr.line_to(15, 6) 365 345 cr.stroke() 366 346 … … 397 377 398 378 399 class AssociationEnd(DiagramItem): 400 """An association end represents one end of an association. An association 379 class AssociationEnd(SubjectSupport): 380 """ 381 An association end represents one end of an association. An association 401 382 has two ends. An association end has two labels: one for the name and 402 383 one for the multiplicity (and maybe one for tagged values in the future). … … 409 390 the first 20-30 units of the line, for association end popup menu. 410 391 """ 411 # __gproperties__ = {412 # 'name': (gobject.TYPE_STRING, 'name', '', '', gobject.PARAM_READWRITE),413 # 'mult': (gobject.TYPE_STRING, 'mult', '', '', gobject.PARAM_READWRITE)414 # }415 # __gproperties__.update(DiagramItem.__gproperties__)416 392 417 393 head_popup_menu = ( … … 436 412 437 413 def __init__(self, owner, id=None, end=None): 438 DiagramItem.__init__(self, id)414 SubjectSupport.__init__(self) 439 415 self._owner = owner 440 416 self._end = end … … 447 423 self._mult_bounds = Rectangle() 448 424 self._point1 = self._point2 = (0, 0) 449 450 def postload(self):451 DiagramItem.postload(self)452 #self.set_text()453 425 454 426 def get_popup_menu(self): … … 478 450 self._mult = m 479 451 self.request_update() 480 481 452 482 453 def get_navigability(self): … … 660 631 661 632 def on_subject_notify(self, pspec, notifiers=()): 662 DiagramItem.on_subject_notify(self, pspec,633 SubjectSupport.on_subject_notify(self, pspec, 663 634 notifiers + ('aggregation', 'visibility', 664 635 'name', 'lowerValue.value', … … 684 655 685 656 def on_subject_notify__upperValue_value(self, upper_value, pspec): 686 log.debug('New value for upperValue.value: %s' % upper_value and upper_value.value)657 #log.debug('New value for upperValue.value: %s' % upper_value and upper_value.value) 687 658 self.set_text() 688 659 self.request_update() gaphor/branches/new-canvas/gaphor/diagram/diagramitem.py
r1085 r1087 13 13 STEREOTYPE_CLOSE = '\xc2\xbb' # '>>' 14 14 15 class DiagramItem(Presentation, Element):15 class SubjectSupport(Presentation, Element): 16 16 """ 17 Basic functionality for all model elements (lines and elements!). 18 19 This class contains common functionallity for model elements and 20 relationships. 21 It provides an interface similar to UML.Element for connecting and 22 disconnecting signals. 23 24 This class is not very useful on its own. It contains some glue-code for 25 diacanvas.DiaCanvasItem and gaphor.UML.Element. 26 27 Example: 28 class ElementItem(dia
