The script creates a simple app with a GUI containing an input field and a button to select a folder. On startup a default value is set to the input field. If the user types a value or selects a folder, the new value is stored and validated. If validation fails, the input field value is appended with the error message (the validation rule is that the value length must be greater than 0).
import Tkinter
import Tkconstants
import functools
import tkFileDialog
import configobj
import validate
from puremvc.patterns.proxy import Proxy
from puremvc.patterns.facade import Facade
from puremvc.patterns.command import SimpleCommand
from puremvc.patterns.mediator import Mediator
from puremvc.interfaces import ICommand, IMediator
class ConfigurationManager(object):
def __init__(self):
self.exec_spec = configobj.ConfigObj({'input_dir':'string(min=1)'}, list_values=False, _inspec=True, interpolation=False)
self.exec_params = configobj.ConfigObj(configspec=self.exec_spec)
def set(self, key, value):
self.exec_params[key] = value
validation_result = self.exec_params.validate(validate.Validator(self.exec_spec), preserve_errors=True)
for sections, key, exception in configobj.flatten_errors(self.exec_params, validation_result):
raise exception
def getValueFor(self, key):
return self.exec_params[key]
class ExecutionParamsProxy(Proxy):
NAME = "ExecutionParamsProxy"
def __init__(self):
super(ExecutionParamsProxy, self).__init__(ExecutionParamsProxy.NAME, [])
self.exec_params = ConfigurationManager()
def init(self):
self.exec_params.set('input_dir', '/path/to/nowhere')
self.sendNotification('defaults_loaded')
def set(self, key, value):
try:
self.exec_params.set(key, value)
except validate.ValidateError, ve:
self.sendNotification('validation_error', {'who':key, 'what':str(ve)})
def getValueFor(self, key):
return self.exec_params.getValueFor(key)
class InputDirectoryMediator(Mediator, IMediator):
NAME = "InputDirectoryMediator"
def __init__(self, view_component):
super(InputDirectoryMediator, self).__init__(InputDirectoryMediator.NAME, view_component)
self.bind(view_component)
self.view_component_key = 'input_dir'
self._notification_handlers = {
'defaults_loaded':self.loadDefaults,
'validation_error':self.handleValidationError
}
def bind(self, view_component):
view_component.trace('w', functools.partial(self.onSet, view_component))
def onSet(self, *args):
view_component = args[0]
value = view_component.get()
self.sendNotification('ExecutionParamSetByUser', (self.view_component_key, value))
def listNotificationInterests(self):
return ['defaults_loaded', 'validation_error']
def handleNotification(self, notification):
name = notification.getName()
handler = self._notification_handlers[name]
handler(notification)
def loadDefaults(self, notification):
exec_params = self.facade.retrieveProxy(ExecutionParamsProxy.NAME)
value = exec_params.getValueFor(self.view_component_key)
self.getViewComponent().set(value)
def handleValidationError(self, notification):
validation_error_data = notification.getBody()
if validation_error_data['who'] == self.view_component_key:
current_value = self.getViewComponent().get()
self.getViewComponent().set(current_value+' <-'+validation_error_data['what'])
class StartupCommand(SimpleCommand, ICommand):
def execute(self, notification):
gui = notification.getBody()
self.facade.registerMediator(InputDirectoryMediator(gui.input_dir))
self.facade.registerProxy(ExecutionParamsProxy())
self.facade.retrieveProxy(ExecutionParamsProxy.NAME).init()
class ExecutionParamSetListener(SimpleCommand, ICommand):
def execute(self, notification):
key, value = notification.getBody()
exec_params = self.facade.retrieveProxy(ExecutionParamsProxy.NAME)
exec_params.set(key, value)
class AppFacade(Facade):
@staticmethod
def getInstance():
return AppFacade()
def initializeController(self):
super(AppFacade, self).initializeController()
self.registerCommand('init', StartupCommand)
self.registerCommand('ExecutionParamSetByUser', ExecutionParamSetListener)
class AppGui(Tkinter.Frame):
def __init__(self, root):
self.root = root
self.input_dir = Tkinter.StringVar()
Tkinter.Frame.__init__(self, root)
Tkinter.Button(self, text='Select directory', command=self.askdirectory).pack(**{'fill': Tkconstants.BOTH, 'padx': 5, 'pady': 5})
Tkinter.Entry(self, textvariable=self.input_dir).pack()
def askdirectory(self):
directory_name = tkFileDialog.askdirectory()
self.input_dir.set(directory_name)
def show(self):
self.pack()
self.root.mainloop()
if __name__ == '__main__':
gui = AppGui(Tkinter.Tk())
app = AppFacade.getInstance()
app.sendNotification('init', body=gui)
gui.show()
Is this a correct implementation of ports and adaptors with PureMVC?