1"""
2Supporting Model/View/Controller (MVC) pattern
3
4Demonstrates one approach to writing Model/View/Controller (MVC)-based
5applications using Traits UI.
6
7This example contains a trivial model containing only one data object, the
8string 'myname'.
9
10In this example, the Controller contains the View. A more rigorous example
11would separate these.
12
13A few key points:
14
15- the Controller itself accesses the model as self.model
16- the Controller's View can access model traits directly ('myname')
17"""
18
19from traits.api import HasTraits, Str, Bool, TraitError
20from traitsui.api import View, VGroup, HGroup, Item, Controller
21
22
23class MyModel(HasTraits):
24    """ Define a simple model containing a single string, 'myname'
25    """
26
27    # Simple model data:
28    myname = Str()
29
30
31class MyViewController(Controller):
32    """ Define a combined controller/view class that validates that
33        MyModel.myname is consistent with the 'allow_empty_string' flag.
34    """
35
36    # When False, the model.myname trait is not allowed to be empty:
37    allow_empty_string = Bool()
38
39    # Last attempted value of model.myname to be set by user:
40    last_name = Str()
41
42    # Define the view associated with this controller:
43    view = View(
44        VGroup(
45            HGroup(
46                Item('myname', springy=True), '10',
47                Item('controller.allow_empty_string', label='Allow Empty')
48            ),
49
50            # Add an empty vertical group so the above items don't end up
51            # centered vertically:
52            VGroup()
53        ),
54        resizable=True
55    )
56
57    #-- Handler Interface ----------------------------------------------------
58
59    def myname_setattr(self, info, object, traitname, value):
60        """ Validate the request to change the named trait on object to the
61            specified value.  Validation errors raise TraitError, which by
62            default causes the editor's entry field to be shown in red.
63            (This is a specially named method <model trait name>_setattr,
64            which is available inside a Controller.)
65        """
66        self.last_name = value
67        if (not self.allow_empty_string) and (value.strip() == ''):
68            raise TraitError('Empty string not allowed.')
69
70        return super(MyViewController, self).setattr(info, object, traitname,
71                                                     value)
72
73    #-- Event handlers -------------------------------------------------------
74
75    def controller_allow_empty_string_changed(self, info):
76        """ 'allow_empty_string' has changed, check the myname trait to ensure
77            that it is consistent with the current setting.
78        """
79        if (not self.allow_empty_string) and (self.model.myname == ''):
80            self.model.myname = '?'
81        else:
82            self.model.myname = self.last_name
83
84# Create the model and (demo) view/controller:
85demo = MyViewController(MyModel())
86
87# Run the demo (if invoked from the command line):
88if __name__ == '__main__':
89    demo.configure_traits()
90