root/gaphor/trunk/gaphor/diagram/classes/dependency.py

Revision 2255, 5.6 kB (checked in by arj..@yirdis.nl, 9 months ago)

moved classes items to seperate package. More unit tests for interface item.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 """
2 Common dependencies likeq dependency, usage, realization and implementation.
3 """
4
5 from gaphor import UML
6
7 #from gaphor.diagram.relationship import Relationship
8 from gaphor.diagram.diagramline import DiagramLine
9
10
11 #class DependencyRelationship(Relationship):
12 #    """
13 #    Relationship for dependencies including realization dependency between
14 #    classifiers and components.
15 #    """
16 #    def relationship(self, line, head_subject = None, tail_subject = None):
17 #        if line.get_dependency_type() == UML.Realization:
18 #            args = ('realizingClassifier', None), ('abstraction', 'realization')
19 #        else:
20 #            args = ('supplier', 'supplierDependency'), ('client', 'clientDependency')
21 #        args +=  head_subject, tail_subject
22 #        return self.find(line, *args)
23
24
25
26 class DependencyItem(DiagramLine):
27     """
28     This class represents all types of dependencies.
29
30     Normally a dependency looks like a dashed line with an arrow head.
31     The dependency can have a stereotype attached to it, stating the kind of
32     dependency we're dealing with. The dependency kind can only be changed if
33     the dependency is not connected to two items.
34
35     In the special case of an Usage dependency, where one end is
36     connected to an InterfaceItem: the line is drawn as a solid line without
37     arrowhead.  The Interface will draw a half a circle on the side where the
38     Usage dep. is connected.
39
40     Although it is possible to add multiple Implementation and Usage
41     dependencies to an interface, it will probably not be very explaining
42     (esp. Usage dependencies).
43
44     Function get_dependency_type should be used to determine automatically
45     type of a dependency.
46
47     TODO (see also InterfaceItem): When a Usage dependency is drawn and is
48           connected to an InterfaceItem, draw a solid line, but stop drawing
49           the line 'x' points before the last handle.
50     """
51
52     __uml__ = UML.Dependency
53
54     # do not use issubclass, because issubclass(UML.Implementation, UML.Realization)
55     # we need to be very strict here
56     __stereotype__ = {
57         'use':        lambda self: self._dependency_type == UML.Usage,
58         'realize':    lambda self: self._dependency_type == UML.Realization,
59         'implements': lambda self: self._dependency_type == UML.Implementation,
60     }
61
62 #    relationship = DependencyRelationship()
63
64     def __init__(self, id=None):
65         DiagramLine.__init__(self, id)
66
67         self._dependency_type = UML.Dependency
68         self.auto_dependency = True
69         self._dash_style = True
70
71     def save(self, save_func):
72         DiagramLine.save(self, save_func)
73         save_func('auto_dependency', self.auto_dependency)
74
75
76     def load(self, name, value):
77         #if name == 'dependency_type':
78         #    self.set_dependency_type(getattr(UML, value))
79         if name == 'auto_dependency':
80             self.auto_dependency = eval(value)
81         else:
82             DiagramLine.load(self, name, value)
83
84     def postload(self):
85         if self.subject:
86             dependency_type = self.subject.__class__
87             DiagramLine.postload(self)
88             self._dependency_type = dependency_type
89         else:
90             DiagramLine.postload(self)
91
92     def get_dependency_type(self):
93         return self._dependency_type
94
95
96     def set_dependency_type(self, dependency_type=None):
97         if not dependency_type and self.auto_dependency:
98             dependency_type = self.determine_dependency_type(self.head.connected_to, self.tail.connected_to)
99         self._dependency_type = dependency_type
100         self.request_update()
101
102     dependency_type = property(lambda s: s._dependency_type,
103                                set_dependency_type, set_dependency_type)
104
105     def post_update(self, context):
106         super(DependencyItem, self).post_update(context)
107
108         from interface import InterfaceItem
109         dependency_type = self._dependency_type
110         c1 = self.head.connected_to
111         if c1 and dependency_type is UML.Usage \
112            and isinstance(c1, InterfaceItem) and c1.is_folded():
113             self._dash_style = False
114         else:
115             self._dash_style = True
116
117     def draw_head(self, context):
118         cr = context.cairo
119         if self._dash_style:
120             cr.set_dash((), 0)
121             cr.move_to(15, -6)
122             cr.line_to(0, 0)
123             cr.line_to(15, 6)
124             cr.stroke()
125         cr.move_to(0, 0)
126    
127     def draw(self, context):
128         if self._dash_style:
129             context.cairo.set_dash((7.0, 5.0), 0)
130         super(DependencyItem, self).draw(context)
131
132     @staticmethod
133     def is_usage(s):
134         """Return true if dependency should be usage dependency.
135         """
136         return isinstance(s, UML.Interface)
137
138
139     @staticmethod
140     def is_realization(ts, hs):
141         """Return true if dependency should be realization dependency.
142         """
143         return isinstance(ts, UML.Classifier) and isinstance(hs, UML.Component)
144
145
146     @staticmethod
147     def determine_dependency_type(ts, hs):
148         """
149         Determine dependency type:
150
151         - check if it is usage
152         - check if it is realization
153         - if none of above, then it is normal dependency
154
155         The checks should be performed in above order. For example if ts and hs
156         are Interface and Component, then we have two choices:
157
158         - claim it is an usage (as ts is an Interface)
159         - or claim it is a realization (as Interface is Classifier, too)
160
161         In this case we want usage to win over realization.
162         """
163         dt = UML.Dependency
164         if DependencyItem.is_usage(ts):
165             dt = UML.Usage
166         elif DependencyItem.is_realization(ts, hs):
167             dt = UML.Realization
168         return dt
169
170 # vim:sw=4:et
Note: See TracBrowser for help on using the browser.