root/gaphor/tags/gaphor-0.2.0/uml2/baseelement.py

Revision 192, 3.4 kB (checked in by arjanmol, 6 years ago)

*** empty log message ***

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/env python
2 # vim:sw=4:et
3 """BaseElement:
4
5 Method names have changed on some places to emphasize that we deal
6 with a completely new data model here.
7
8 save()/load()/postload()
9     Load/save the element.
10
11 unlink()
12     Remove all references to the element. First of all the signal
13     '__unlink__' is send to all attached signals.
14
15 attach ('name', callback, *data) or
16 attach (('name', 'other_property'), callback, *data)
17     Connect 'callback' to recieve notifications if one of the properties
18     change (the latter being more memory efficient if you want to listen on
19     more properties). The listener will recieve the property name as
20     first argument, followed by *data.
21
22 detach (callback, *data)
23     Disconnect callback as listener.
24
25 notify (name)
26     Notify all listeners the property 'name' has changed.
27 """
28
29 import types
30
31 class BaseElement(object):
32     """Base class for UML data classes."""
33
34     def __init__(self):
35         self._observers = dict()
36         self._block_notify = 0
37
38     def save(self, save_func):
39         """Save the state by calling save_func(name, value)."""
40         clazz = self.__class__
41         for prop in dir(clazz):
42             if isinstance(prop, umlproperty):
43                 prop.save(self, save_func)
44
45     def load(self, name, value):
46         """Loads value in name. Make sure that for every load postload()
47         should be called."""
48         self._block_notify = True
49         clazz = self.__class__
50         try:
51             prop = getattr(clazz, name)
52         except AttributeError, e:
53             print "'%s' has no property '%s'" % (clazz.__name__, name)
54         else:
55             prop.load(self, value)
56
57     def postload(self):
58         self._block_notify = False
59
60     def unlink(self):
61         self.notify('__unlink__')
62    
63     def attach(self, names, callback, *data):
64         """Attach 'callback' to a list of names. Names may also be a string."""
65         if type(names) is types.StringType:
66             names = (names,)
67         cb = (callback,) + data
68         for name in names:
69             try:
70                 self._observers[name].append(cb)
71             except KeyError:
72                 # create new entry
73                 self._observers[name] = [cb]
74
75     def detach(self, callback, *data):
76         """Detach a callback identified by it's data."""
77         cb = (callback,) + data
78         for name, values in self._observers.items():
79             if cb in values:
80                 values.remove(cb)
81
82     def notify(self, name):
83         """Send notification to attached callbacks that a property
84         has changed."""
85         if self._block_notify:
86             return
87         cb_list = self._observers.get(name) or ()
88         for cb_data in cb_list:
89             try:
90                 apply(cb_data[0], (name,) + cb_data[1:])
91             except:
92                 pass
93
94     # OCL methods: (from SMW by Ivan Porres (http://www.abo.fi/~iporres/smw))
95
96     def isKindOf(self,clazz):
97         """Returns true if the object is an instance of clazz."""
98         return isinstance(self, clazz)
99
100     def isTypeOf(self, other):
101         """Returns true if the object is of the same type as other."""
102         return type(self) == type(other)
103
104
105 if __name__ == '__main__':
106     a = BaseElement()
107     b = BaseElement()
108     def cb_func(name, *args):
109         print '  cb_func:', name, args
110
111     a.attach('ev1', cb_func, a)
112     a.attach('ev1', cb_func, a)
113     a.attach('ev2', cb_func, 'ev2', a)
114
115     print 'notify: ev1'
116     a.notify('ev1')
117     print 'notify: ev2'
118     a.notify('ev2')
119  
120     a.detach(cb_func, a)
121
122     print 'notify: ev1'
123     a.notify('ev1')
124     print 'notify: ev2'
125     a.notify('ev2')
126  
Note: See TracBrowser for help on using the browser.