root/gaphor/tags/gaphor-0.3.0/gaphor/UML/elementfactory.py

Revision 251, 4.6 kB (checked in by arjanmol, 5 years ago)

*** empty log message ***

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 # vim: sw=4
2 """elementfactory.py
3 """
4
5 import gaphor
6 import gaphor.misc.uniqueid as uniqueid
7 #import weakref
8 from element import Element
9 from diagram import Diagram
10 #from gaphor.misc.weakmethod import WeakMethod
11
12 class ElementFactory(object):
13     """The ElementFactory is used to create elements ans do lookups to
14     elements. A model can contain only one Model element, though.
15
16     Notifications are send with as arguments (name, element, *user_data).
17     The following names are used:
18     create - a new model element is created (element is newly created element)
19     remove - a model element is removed (element is to be removed element)
20     model - a new model has been loaded (element is None)
21     flush - model is flushed: all element are removed from the factory
22             (element is None)
23     """
24     def __init__(self):
25         self._elements = dict()
26         self._observers = list()
27
28     def create(self, type):
29         """Create a new Model element of type type"""
30         return self.create_as(type, uniqueid.generate_id())
31
32     def create_as(self, type, id):
33         """Create a new model element of type 'type' with 'id' as its ID.
34         This method should only be used when loading models. If the ID is
35         higher that the current id that should be used for the next item, the
36         ID for the next item is set to id + 1."""
37         assert issubclass(type, Element)
38         obj = type(id, self)
39         self._elements[id] = obj
40         #obj.connect('__unlink__', self.__element_signal, weakref.ref(obj))
41         obj.connect('__unlink__', self.__element_signal)
42         self.notify(obj, 'create')
43         return obj
44
45     def lookup(self, id):
46         try:
47             return self._elements[id]
48         except KeyError:
49             return None
50
51     def select(self, expression):
52         """Create a list of elements that comply with expression."""
53         l = []
54         for e in self._elements.values():
55             if expression(e):
56                 l.append(e)
57         return l
58
59     def keys(self):
60         return self._elements.keys()
61
62     def iterkeys(self):
63         return self._elements.iterkeys()
64
65     def values(self):
66         return self._elements.values()
67
68     def itervalues(self):
69         return self._elements.itervalues()
70
71     def is_empty(self):
72         """Returns True if the factory holds no elements."""
73         if self._elements:
74             return False
75         else:
76             return True
77
78     def flush(self):
79         """Flush all elements (remove them from the factory)."""
80         self.notify(None, 'flush')
81         # First flush all diagrams:
82         for value in self.select(lambda e: isinstance(e, Diagram)):
83             value.unlink()
84
85         for key, value in self._elements.items():
86             #print 'ElementFactory: unlinking', value
87             #print 'references:', gc.get_referrers(value)
88             value.unlink()
89
90         assert len(self._elements) == 0, 'Still items in the factory: %s' % str(self._elements.values())
91
92         import gc
93         for i in range(4): gc.collect()
94
95     def connect(self, callback, *data):
96         """Attach 'callback'."""
97         self._observers.append((callback,) + data)
98
99     def disconnect(self, callback, *data):
100         """Detach a callback identified by it's data."""
101         #print 'disconnect', callback, data
102         cb = (callback,) + data
103         # Remove all occurences of 'cb' from values
104         # (if none is found ValueError is raised).
105         try:
106             while True:
107                 self._observers.remove(cb)
108         except ValueError:
109             pass
110
111     def notify(self, element, name):
112         """Send notification to attached callbacks that a property
113         has changed. This is usually only called by the properties."""
114         for cb_data in self._observers:
115             try:
116                 apply(cb_data[0], (element, name) + cb_data[1:])
117             except:
118                 pass
119
120     def notify_model(self):
121         self.notify(None, 'model')
122
123     def __element_signal(self, element, pspec):
124         """Remove an element from the factory """
125         #element = weak_element()
126         #if not element: return
127         #log.debug('element %s send signal %s' % (element, name))
128         if pspec == '__unlink__' and self._elements.has_key(element.id):
129             #log.debug('Unlinking element: %s' % element)
130             del self._elements[element.id]
131             self.notify(element, 'remove')
132         elif pspec == '__relink__' and not self._elements.has_key(element.id):
133             log.debug('Relinking element: %s' % element)
134             self._elements[element.id] = element
135             self.notify(element, 'create')
136
137 # Make one ElementFactory instance an application-wide resource
138 gaphor.resource(ElementFactory)
Note: See TracBrowser for help on using the browser.