1 """
2 PureMVC Python Port by Toby de Havilland <toby.de.havilland@puremvc.org>
3 PureMVC Python Port by Daniele Esposti <expo@expobrain.net>
4 PureMVC - Copyright(c) 2006-08 Futurescale, Inc., Some rights reserved.
5 Your reuse is governed by the Creative Commons Attribution 3.0 License
6 """
7
8 from puremvc import MultitonError
9 import puremvc.interfaces
10 import puremvc.patterns.observer
11
12
13 -class Facade(puremvc.interfaces.IFacade):
14 """
15 A base Multiton C{IFacade} implementation.
16
17 In PureMVC, the C{Facade} class assumes these
18 responsibilities:
19
20 Initializing the C{Model}, C{View} and C{Controller} Singletons.
21
22 Providing all the methods defined by the C{IModel, IView, & IController} interfaces.
23
24 Providing the ability to override the specific C{Model}, C{View} and C{Controller} Singletons created.
25
26 Providing a single point of contact to the application for registering C{Commands} and notifying C{Observers}
27
28
29 @see: L{Model<puremvc.core.Model>}
30 @see: L{View<puremvc.core.View>}
31 @see: L{Controller<puremvc.core.Controller>}
32 @see: L{Notification<puremvc.patterns.observer.Notification>}
33 @see: L{Mediator<puremvc.patterns.mediator.Mediator>}
34 @see: L{Proxy<puremvc.patterns.proxy.Proxy>}
35 @see: L{SimpleCommand<puremvc.patterns.command.SimpleCommand>}
36 @see: L{MacroCommand<puremvc.patterns.command.MacroCommand>}
37 """
38
39 """The Multiton Facade instanceMap."""
40 instanceMap = {}
41
42 """Message Constants"""
43 MULTITON_MSG = "Facade instance for this Multiton key already constructed!"
44
46 """
47 Constructor.
48
49 This C{IFacade} implementation is a Multiton, so you should not call
50 the constructor directly, but instead call the static Factory method,
51 passing the unique key for this instance
52 C{Facade.getInstance( multitonKey )}
53
54 @raise MultitonError: if instance for this Multiton key has already
55 been constructed
56 """
57
58 self.controller = None
59 self.model = None
60 self.view = None
61
62
63 self.multitonKey = key
64
65 if self.instanceMap.get(key):
66 raise MultitonError(self.MULTITON_MSG)
67
68 self.initializeNotifier(key)
69 self.instanceMap[key] = self
70
71 self.initializeFacade()
72
74 """
75 Initialize the Multiton C{Facade} instance.
76
77 Called automatically by the constructor. Override in your subclass to
78 do any subclass specific initializations. Be sure to call
79 C{super.initializeFacade()}, though.
80 """
81 self.initializeController()
82 self.initializeModel()
83 self.initializeView()
84
85 @classmethod
87 """
88 Facade Multiton Factory method
89
90 @return: the Multiton instance of the Facade
91 """
92 if cls.instanceMap.get(key) is None:
93 cls.instanceMap[key] = cls(key)
94
95 return cls.instanceMap[key]
96
98 """
99 Initialize the C{Controller}.
100
101 Called by the C{initializeFacade} method.
102 Override this method in your subclass of C{Facade}
103 if one or both of the following are true:
104
105 You wish to initialize a different C{IController}.
106 You have C{Commands} to register with the C{Controller} at startup.
107
108 If you don't want to initialize a different C{IController},
109 call C{super.initializeController()} at the beginning of your method, then register C{Proxy}s.
110
111 Note: This method is <i>rarely<i> overridden; in practice you are more
112 likely to use a C{Command} to create and register C{Proxy}s
113 with the C{Model}, since C{Proxy}s with mutable data will likely
114 need to send C{INotification}s and thus will likely want to fetch a reference to
115 the C{Facade} during their construction.
116 """
117 if self.controller is None:
118 from puremvc.core import Controller
119
120 self.controller = Controller.getInstance(self.multitonKey)
121
123 """
124 Initialize the C{Model}.
125
126 Called by the C{initializeFacade} method.
127 Override this method in your subclass of C{Facade}
128 if one or both of the following are true:
129
130 You wish to initialize a different C{IModel}.
131
132 You have C{Proxy}s to register with the Model that do not
133 retrieve a reference to the Facade at construction time.
134
135 If you don't want to initialize a different C{IModel},
136 call C{super.initializeModel()} at the beginning of your
137 method, then register C{Proxy}s.
138
139 Note: This method is <i>rarely</i> overridden; in practice you are more
140 likely to use a C{Command} to create and register C{Proxy}s with the
141 C{Model}, since C{Proxy}s with mutable data will likely need to send
142 C{INotification}s and thus will likely want to fetch a reference to
143 the C{Facade} during their construction.
144 """
145 if self.model is None:
146 from puremvc.core import Model
147
148 self.model = Model.getInstance(self.multitonKey)
149
151 """
152 Initialize the C{View}.
153
154 Called by the C{initializeFacade} method.
155 Override this method in your subclass of C{Facade}
156 if one or both of the following are true:
157
158 You wish to initialize a different C{IView}.
159
160 You have C{Observers} to register with the C{View}
161
162 If you don't want to initialize a different C{IView},
163 call C{super.initializeView()} at the beginning of your
164 method, then register C{IMediator} instances.
165
166 Note: This method is <i>rarely</i> overridden; in practice you are more
167 likely to use a C{Command} to create and register C{Mediator}s with the
168 C{View}, since C{IMediator} instances will need to send
169 C{INotification}s and thus will likely want to fetch a reference
170 to the C{Facade} during their construction.
171 """
172 if self.view is None:
173 from puremvc.core import View
174
175 self.view = View.getInstance(self.multitonKey)
176
178 """
179 Register an C{ICommand} with the C{Controller} by Notification name.
180
181 @param notificationName: the name of the C{INotification} to associate the C{ICommand} with
182 @param commandClassRef: a reference to the Class of the C{ICommand}
183 """
184 self.controller.registerCommand(notificationName, commandClassRef)
185
187 """
188 Remove a previously registered C{ICommand} to C{INotification} mapping from the Controller.
189
190 @param notificationName: the name of the C{INotification} to remove the C{ICommand} mapping for
191 """
192 self.controller.removeCommand(notificationName)
193
195 """
196 Check if a Command is registered for a given Notification
197
198 @param notificationName: the name of the C{INotification}
199 @return: whether a Command is currently registered for the given C{notificationName}.
200 """
201 return self.controller.hasCommand(notificationName)
202
204 """
205 Register an C{IProxy} with the C{Model} by name.
206
207 @param proxy: the C{IProxy} instance to be registered with the C{Model}.
208 """
209 self.model.registerProxy(proxy)
210
212 """
213 Retrieve an C{IProxy} from the C{Model} by name.
214
215 @param proxyName: the name of the proxy to be retrieved.
216 @return: the C{IProxy} instance previously registered with the given C{proxyName}.
217 """
218 return self.model.retrieveProxy(proxyName)
219
221 """
222 Remove an C{IProxy} from the C{Model} by name.
223
224 @param proxyName: the C{IProxy} to remove from the C{Model}.
225 @return: the C{IProxy} that was removed from the C{Model}
226 """
227 if self.model:
228 return self.model.removeProxy(proxyName)
229
231 """
232 Check if a Proxy is registered
233
234 @param proxyName: the name of the C{IProxy}
235 @return: whether a Proxy is currently registered with the given C{proxyName}.
236 """
237 return self.model.hasProxy(proxyName)
238
247
256
266
275
277 """
278 Create and send an C{INotification}.
279
280 Keeps us from having to construct new notification
281 instances in our implementation code.
282
283 @param notificationName: the name of the notiification to send
284 @param body: the body of the notification (optional)
285 @param noteType: the type of the notification (optional)
286 """
287 self.notifyObservers(puremvc.patterns.observer.Notification(notificationName, body, noteType))
288
290 """
291 Notify C{Observer}s.
292
293 This method is left public mostly for backward
294 compatibility, and to allow you to send custom
295 notification classes using the facade.
296
297 Usually you should just call sendNotification
298 and pass the parameters, never having to
299 construct the notification yourself.
300
301 @param notification: the C{INotification} to have the C{View} notify C{Observers} of.
302 """
303 if (self.view is not None):
304 self.view.notifyObservers(notification)
305
307 """
308 Set the Multiton key for this facade instance.
309
310 Not called directly, but instead from the constructor when getInstance
311 is invoked. It is necessary to be public in order to implement
312 INotifier.
313 """
314 self.multitonKey = key
315
316 @classmethod
318 """
319 Check if a Core is registered or not
320
321 @param key: the multiton key for the Core in question
322 @return: whether a Core is registered with the given C{key}.
323 """
324 return cls.instanceMap.get(key) is not None
325
326 @classmethod
344