KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > prefuse > action > layout > AxisLayout


1 package prefuse.action.layout;
2
3 import java.awt.geom.Rectangle2D JavaDoc;
4 import java.util.Iterator JavaDoc;
5
6 import prefuse.Constants;
7 import prefuse.data.Table;
8 import prefuse.data.Tuple;
9 import prefuse.data.expression.Predicate;
10 import prefuse.data.query.NumberRangeModel;
11 import prefuse.data.query.ObjectRangeModel;
12 import prefuse.data.tuple.TupleSet;
13 import prefuse.util.DataLib;
14 import prefuse.util.MathLib;
15 import prefuse.util.ui.ValuedRangeModel;
16 import prefuse.visual.VisualItem;
17
18 /**
19  * Layout Action that assigns positions along a single dimension (either x or
20  * y) according to a specified data field. By default, the range of values
21  * along the axis is automatically determined by the minimum and maximum
22  * values of the data field. The range bounds can be manually set using the
23  * {@link #setRangeModel(ValuedRangeModel)} method. Also, the set of items
24  * processed by this layout can be filtered by providing a filtering
25  * predicate (@link #setFilter(Predicate)).
26  *
27  * @author <a HREF="http://jheer.org">jeffrey heer</a>
28  */

29 public class AxisLayout extends Layout {
30
31     private String JavaDoc m_field;
32     private int m_scale = Constants.LINEAR_SCALE;
33     private int m_axis = Constants.X_AXIS;
34     private int m_type = Constants.UNKNOWN;
35     
36     // visible region of the layout (in item coordinates)
37
// if false, the table will be consulted
38
private boolean m_modelSet = false;
39     private ValuedRangeModel m_model = null;
40     private Predicate m_filter = null;
41     
42     // screen coordinate range
43
private double m_min;
44     private double m_range;
45     
46     // value range / distribution
47
private double[] m_dist = new double[2];
48     
49     /**
50      * Create a new AxisLayout. Defaults to using the x-axis.
51      * @param group the data group to layout
52      * @param field the data field upon which to base the layout
53      */

54     public AxisLayout(String JavaDoc group, String JavaDoc field) {
55         super(group);
56         m_field = field;
57     }
58     
59     /**
60      * Create a new AxisLayout.
61      * @param group the data group to layout
62      * @param field the data field upon which to base the layout
63      * @param axis the axis type, either {@link prefuse.Constants#X_AXIS}
64      * or {@link prefuse.Constants#Y_AXIS}.
65      */

66     public AxisLayout(String JavaDoc group, String JavaDoc field, int axis) {
67         this(group, field);
68         setAxis(axis);
69     }
70     
71     /**
72      * Create a new AxisLayout.
73      * @param group the data group to layout
74      * @param field the data field upon which to base the layout
75      * @param axis the axis type, either {@link prefuse.Constants#X_AXIS}
76      * or {@link prefuse.Constants#Y_AXIS}.
77      * @param filter an optional predicate filter for limiting which items
78      * to layout.
79      */

80     public AxisLayout(String JavaDoc group, String JavaDoc field, int axis, Predicate filter) {
81         this(group, field, axis);
82         setFilter(filter);
83     }
84
85     // ------------------------------------------------------------------------
86

87     /**
88      * Set the data field used by this axis layout action. The values of the
89      * data field will determine the position of items along the axis. Note
90      * that this method does not affect the other parameters of this action. In
91      * particular, clients that have provided a custom range model for
92      * setting the axis range may need to appropriately update the model
93      * setting for use with the new data field setting.
94      * @param field the name of the data field that determines the layout
95      */

96     public void setDataField(String JavaDoc field) {
97         m_field = field;
98         if ( !m_modelSet )
99             m_model = null;
100     }
101     
102     /**
103      * Get the data field used by this axis layout action. The values of the
104      * data field determine the position of items along the axis.
105      * @return the name of the data field that determines the layout
106      */

107     public String JavaDoc getDataField() {
108         return m_field;
109     }
110     
111     /**
112      * Set the range model determing the span of the axis. This model controls
113      * the minimum and maximum values of the layout, as provided by the
114      * {@link prefuse.util.ui.ValuedRangeModel#getLowValue()} and
115      * {@link prefuse.util.ui.ValuedRangeModel#getHighValue()} methods.
116      * @param model the range model for the axis.
117      */

118     public void setRangeModel(ValuedRangeModel model) {
119         m_model = model;
120         m_modelSet = (model != null);
121     }
122     
123     /**
124      * Get the range model determing the span of the axis. This model controls
125      * the minimum and maximum values of the layout, as provided by the
126      * {@link prefuse.util.ui.ValuedRangeModel#getLowValue()} and
127      * {@link prefuse.util.ui.ValuedRangeModel#getHighValue()} methods.
128      * @return the range model for the axis.
129      */

130     public ValuedRangeModel getRangeModel() {
131         return m_model;
132     }
133     
134     /**
135      * Set a predicate filter to limit which items are considered for layout.
136      * Only items for which the predicate returns a true value are included
137      * in the layout computation.
138      * @param filter the predicate filter to use. If null, no filtering
139      * will be performed.
140      */

141     public void setFilter(Predicate filter) {
142         m_filter = filter;
143     }
144     
145     /**
146      * Get the predicate filter to limit which items are considered for layout.
147      * Only items for which the predicate returns a true value are included
148      * in the layout computation.
149      * @return the predicate filter used by this layout. If null, no filtering
150      * is performed.
151      */

152     public Predicate getFilter() {
153         return m_filter;
154     }
155     
156     // ------------------------------------------------------------------------
157

158     /**
159      * Returns the scale type used for the axis. This setting only applies
160      * for numerical data types (i.e., when axis values are from a
161      * <code>NumberValuedRange</code>).
162      * @return the scale type. One of
163      * {@link prefuse.Constants#LINEAR_SCALE},
164      * {@link prefuse.Constants#SQRT_SCALE}, or
165      * {@link Constants#LOG_SCALE}.
166      */

167     public int getScale() {
168         return m_scale;
169     }
170     
171     /**
172      * Sets the scale type used for the axis. This setting only applies
173      * for numerical data types (i.e., when axis values are from a
174      * <code>NumberValuedRange</code>).
175      * @param scale the scale type. One of
176      * {@link prefuse.Constants#LINEAR_SCALE},
177      * {@link prefuse.Constants#SQRT_SCALE}, or
178      * {@link Constants#LOG_SCALE}.
179      */

180     public void setScale(int scale) {
181         if ( scale < 0 || scale >= Constants.SCALE_COUNT )
182             throw new IllegalArgumentException JavaDoc(
183                     "Unrecognized scale value: "+scale);
184         m_scale = scale;
185     }
186     
187     /**
188      * Return the axis type of this layout, either
189      * {@link prefuse.Constants#X_AXIS} or {@link prefuse.Constants#Y_AXIS}.
190      * @return the axis type of this layout.
191      */

192     public int getAxis() {
193         return m_axis;
194     }
195
196     /**
197      * Set the axis type of this layout.
198      * @param axis the axis type to use for this layout, either
199      * {@link prefuse.Constants#X_AXIS} or {@link prefuse.Constants#Y_AXIS}.
200      */

201     public void setAxis(int axis) {
202         if ( axis < 0 || axis >= Constants.AXIS_COUNT )
203             throw new IllegalArgumentException JavaDoc(
204                     "Unrecognized axis value: "+axis);
205         m_axis = axis;
206     }
207     
208     /**
209      * Return the data type used by this layout. This value is one of
210      * {@link prefuse.Constants#NOMINAL}, {@link prefuse.Constants#ORDINAL},
211      * {@link prefuse.Constants#NUMERICAL}, or
212      * {@link prefuse.Constants#UNKNOWN}.
213      * @return the data type used by this layout
214      */

215     public int getDataType() {
216         return m_type;
217     }
218     
219     /**
220      * Set the data type used by this layout.
221      * @param type the data type used by this layout, one of
222      * {@link prefuse.Constants#NOMINAL}, {@link prefuse.Constants#ORDINAL},
223      * {@link prefuse.Constants#NUMERICAL}, or
224      * {@link prefuse.Constants#UNKNOWN}.
225      */

226     public void setDataType(int type) {
227         if ( type < 0 || type >= Constants.DATATYPE_COUNT )
228             throw new IllegalArgumentException JavaDoc(
229                     "Unrecognized data type value: "+type);
230         m_type = type;
231     }
232     
233     // ------------------------------------------------------------------------
234

235     /**
236      * @see prefuse.action.Action#run(double)
237      */

238     public void run(double frac) {
239         TupleSet ts = m_vis.getGroup(m_group);
240         setMinMax();
241         
242         switch ( getDataType(ts) ) {
243         case Constants.NUMERICAL:
244             numericalLayout(ts);
245             break;
246         default:
247             ordinalLayout(ts);
248         }
249     }
250     
251     /**
252      * Retrieve the data type.
253      */

254     protected int getDataType(TupleSet ts) {
255         if ( m_type == Constants.UNKNOWN ) {
256             boolean numbers = true;
257             if ( ts instanceof Table ) {
258                 numbers = ((Table)ts).canGetDouble(m_field);
259             } else {
260                 for ( Iterator JavaDoc it = ts.tuples(); it.hasNext(); ) {
261                     if ( !((Tuple)it.next()).canGetDouble(m_field) ) {
262                         numbers = false;
263                         break;
264                     }
265                 }
266             }
267             if ( numbers ) {
268                 return Constants.NUMERICAL;
269             } else {
270                 return Constants.ORDINAL;
271             }
272         } else {
273             return m_type;
274         }
275     }
276     
277     /**
278      * Set the minimum and maximum pixel values.
279      */

280     private void setMinMax() {
281         Rectangle2D JavaDoc b = getLayoutBounds();
282         if ( m_axis == Constants.X_AXIS ) {
283             m_min = b.getMinX();
284             m_range = b.getMaxX() - m_min;
285         } else {
286             m_min = b.getMaxY();
287             m_range = b.getMinY() - m_min;
288         }
289     }
290     
291     /**
292      * Set the layout position of an item.
293      */

294     protected void set(VisualItem item, double frac) {
295         double xOrY = m_min + frac*m_range;
296         if ( m_axis == Constants.X_AXIS ) {
297             setX(item, null, xOrY);
298         } else {
299             setY(item, null, xOrY);
300         }
301     }
302     
303     /**
304      * Compute a quantitative axis layout.
305      */

306     protected void numericalLayout(TupleSet ts) {
307         if ( !m_modelSet ) {
308             m_dist[0] = DataLib.min(ts, m_field).getDouble(m_field);
309             m_dist[1] = DataLib.max(ts, m_field).getDouble(m_field);
310             
311             double lo = m_dist[0], hi = m_dist[1];
312             if ( m_model == null ) {
313                 m_model = new NumberRangeModel(lo, hi, lo, hi);
314             } else {
315                 ((NumberRangeModel)m_model).setValueRange(lo, hi, lo, hi);
316             }
317         } else {
318             m_dist[0] = ((Number JavaDoc)m_model.getLowValue()).doubleValue();
319             m_dist[1] = ((Number JavaDoc)m_model.getHighValue()).doubleValue();
320         }
321         
322         Iterator JavaDoc iter = m_vis.items(m_group, m_filter);
323         while ( iter.hasNext() ) {
324             VisualItem item = (VisualItem)iter.next();
325             double v = item.getDouble(m_field);
326             double f = MathLib.interp(m_scale, v, m_dist);
327             set(item, f);
328         }
329     }
330     
331     /**
332      * Compute an ordinal axis layout.
333      */

334     protected void ordinalLayout(TupleSet ts) {
335         if ( !m_modelSet) {
336             Object JavaDoc[] array = DataLib.ordinalArray(ts, m_field);
337             
338             if ( m_model == null ) {
339                 m_model = new ObjectRangeModel(array);
340             } else {
341                 ((ObjectRangeModel)m_model).setValueRange(array);
342             }
343         }
344         
345         ObjectRangeModel model = (ObjectRangeModel)m_model;
346         int start = model.getValue();
347         int end = start + model.getExtent();
348         double total = (double)(end-start);
349         
350         Iterator JavaDoc iter = m_vis.items(m_group, m_filter);
351         while ( iter.hasNext() ) {
352             VisualItem item = (VisualItem)iter.next();
353             int order = model.getIndex(item.get(m_field)) - start;
354             set(item, order/total);
355         }
356     }
357     
358 } // end of class AxisLayout
359
Popular Tags