1#-------------------------------------------------------------------------------
2#
3#  A simple scatter-plot template defined as a test for the template package.
4#
5#  Written by: David C. Morrill
6#  (based on the original cp.plot geo_scatter_plot.py file)
7#
8#  Date: 07/30/2007
9#
10#  (c) Copy 2007 by Enthought, Inc.
11#
12#-------------------------------------------------------------------------------
13
14""" A simple scatter-plot template defined as a test for the template package.
15"""
16
17#-------------------------------------------------------------------------------
18#  Imports:
19#-------------------------------------------------------------------------------
20
21from traits.api \
22    import HasPrivateTraits, Undefined
23
24from traitsui.api \
25    import View, VGroup, Item, Label, Theme, TextEditor
26
27from traitsui.wx.themed_slider_editor \
28    import ThemedSliderEditor
29
30from traitsui.wx.themed_text_editor \
31    import ThemedTextEditor
32
33from chaco.api \
34    import ScatterPlot, ArrayPlotData, Plot
35
36from chaco.tools.api \
37    import PanTool, SimpleZoom
38
39from enable.api \
40    import ColorTrait
41
42from chaco.scatter_markers \
43    import marker_trait
44
45from apptools.template.api \
46    import Template, TRange, TStr, TDerived, TDataSource
47
48from apptools.template.impl.api \
49    import TemplateDataSource, ValueDataNameItem
50
51from .enable_editor \
52    import EnableEditor
53
54#-------------------------------------------------------------------------------
55#  Trait definitions:
56#-------------------------------------------------------------------------------
57
58# Template color trait:
59TColor = ColorTrait( template = 'copy' )
60
61#-------------------------------------------------------------------------------
62#  'ScatterPlot' class:
63#-------------------------------------------------------------------------------
64
65class ScatterPlot ( Template ):
66
67    #-- Template Traits --------------------------------------------------------
68
69    # The plot index data source:
70    index = TDataSource
71
72    # The plot value data source:
73    value = TDataSource
74
75    # The title of the plot:
76    title = TStr( 'Scatter Plot' )
77
78    # The type of marker to use.  This is a mapped trait using strings as the
79    # keys:
80    marker = marker_trait( template = 'copy', event = 'update' )
81
82    # The pixel size of the marker (doesn't include the thickness of the
83    # outline):
84    marker_size = TRange( 1, 5, 1, event = 'update' )
85
86    # The thickness, in pixels, of the outline to draw around the marker.  If
87    # this is 0, no outline will be drawn.
88    line_width = TRange( 0.0, 5.0, 1.0 )
89
90    # The fill color of the marker:
91    color = TColor( 'red', event = 'update' )
92
93    # The color of the outline to draw around the marker
94    outline_color = TColor( 'black', event = 'update' )
95
96    #-- Derived Traits ---------------------------------------------------------
97
98    plot = TDerived # Instance( ScatterPlot )
99
100    #-- Traits UI Views --------------------------------------------------------
101
102    # The scatter plot view:
103    template_view = View(
104        VGroup(
105            Item( 'title',
106                  show_label = False,
107                  style      = 'readonly',
108                  editor     = ThemedTextEditor(
109                                 theme = Theme( '@GBB', alignment = 'center' ) )
110            ),
111            Item( 'plot',
112                  show_label = False,
113                  resizable  = True,
114                  editor     = EnableEditor(),
115                  item_theme = Theme( '@GF5', margins = 0 )
116            )
117        ),
118        resizable = True
119    )
120
121    # The scatter plot options view:
122    options_view = View(
123        VGroup(
124            VGroup(
125                Label( 'Scatter Plot Options',
126                       item_theme = Theme( '@GBB', alignment = 'center' ) ),
127                show_labels = False
128            ),
129            VGroup(
130                Item( 'title', editor = TextEditor() ),
131                Item( 'marker' ),
132                Item( 'marker_size', editor = ThemedSliderEditor() ),
133                Item( 'line_width',
134                      label  = 'Line Width',
135                      editor = ThemedSliderEditor() ),
136                Item( 'color',         label = 'Fill Color' ),
137                Item( 'outline_color', label = 'Outline Color' ),
138                group_theme = Theme( '@GF5', margins = ( -5, -1 ) ),
139                item_theme  = Theme( '@G0B', margins = 0 )
140            )
141        )
142    )
143
144    #-- Default Values ---------------------------------------------------------
145
146    def _index_default ( self ):
147        """ Returns the default value for the 'index' trait.
148        """
149        return TemplateDataSource(
150                   items       = [ ValueDataNameItem( name    = 'index',
151                                                      flatten = True ) ],
152                   description = 'Scatter Plot Index' )
153
154    def _value_default ( self ):
155        """ Returns the default value for the 'value' trait.
156        """
157        return TemplateDataSource(
158                   items       = [ ValueDataNameItem( name    = 'value',
159                                                      flatten = True ) ],
160                   description = 'Scatter Plot Value' )
161
162    #-- ITemplate Interface Implementation -------------------------------------
163
164    def activate_template ( self ):
165        """ Converts all contained 'TDerived' objects to real objects using the
166            template traits of the object. This method must be overridden in
167            subclasses.
168
169            Returns
170            -------
171            None
172        """
173        # If our data sources are still unbound, then just exit; someone must
174        # have marked them as optional:
175        if ((self.index.context_data is Undefined) or
176            (self.value.context_data is Undefined)):
177            return
178
179        # Create a plot data object and give it this data:
180        pd = ArrayPlotData()
181        pd.set_data( 'index', self.index.context_data )
182        pd.set_data( 'value', self.value.context_data )
183
184        # Create the plot:
185        self.plot = plot = Plot( pd )
186        plot.plot(      ( 'index', 'value' ),
187                        type           = 'scatter',
188                        index_sort     = 'ascending',
189                        marker         = self.marker,
190                        color          = self.color,
191                        outline_color  = self.outline_color,
192                        marker_size    = self.marker_size,
193                        line_width     = self.line_width,
194                        bgcolor        = 'white' )
195        plot.trait_set( padding_left   = 50,
196                        padding_right  = 0,
197                        padding_top    = 0,
198                        padding_bottom = 20 )
199
200        # Attach some tools to the plot:
201        plot.tools.append( PanTool( plot, constrain_key = 'shift' ) )
202        zoom = SimpleZoom( component = plot, tool_mode = 'box',
203                           always_on = False )
204        plot.overlays.append( zoom )
205
206    #-- Trait Event Handlers ---------------------------------------------------
207
208    def _update_changed ( self ):
209        """ Handles a plot option being changed.
210        """
211        self.plot = Undefined
212
213