/Users/lyon/j4p/src/gui/run/ObservableSlider.java

1    // Glenn Josefiak 
2    // Fairfield University 
3    // SW513 
4    // Spring 2003 
5     
6    package gui.run; 
7     
8     
9    import javax.swing.*; 
10   import javax.swing.event.ChangeEvent; 
11   import javax.swing.event.ChangeListener; 
12   import java.awt.*; 
13   import java.text.DecimalFormat; 
14   import java.util.Hashtable; 
15   import java.util.Observer; 
16    
17   /** 
18    * A slider with floating point values, a name label, and built-in 
19    * tick labels. 
20    */ 
21   public final class ObservableSlider extends JPanel { 
22       private final int JSLIDER_MIN = 0; 
23       private final int JSLIDER_MAX = 1000; 
24    
25       private final JSlider js; 
26       private final JLabel lblDescription; 
27       private JLabel lblValue; 
28       private final JPanel pnlLabels; 
29    
30       private final Hashtable hshLabelTable; 
31       private final ObservableFloat sliderPosition; 
32       private final DecimalFormat df; 
33       private float sliderMin = 0.0f; 
34       private float sliderMax = 100.0f; 
35       private boolean isLogScale = false; 
36    
37       /** 
38        * Construct a new ObservableSlider ranging from 0.0f to 100.0f 
39        */ 
40       public ObservableSlider() { 
41           hshLabelTable = new Hashtable(); 
42           sliderPosition = new ObservableFloat(); 
43           df = new DecimalFormat("##0.000"); 
44           setLayout(new BorderLayout()); 
45    
46           js = new JSlider(SwingConstants.VERTICAL, JSLIDER_MIN, 
47                   JSLIDER_MAX, JSLIDER_MIN); 
48           js.addChangeListener(new ChangeListener() { 
49               public void stateChanged(final ChangeEvent e) { 
50                   final float val = intToDouble(js.getValue()); 
51                   sliderPosition.setValue(val); 
52                   lblValue.setText(df.format(val)); 
53               } 
54           }); 
55           add(js, BorderLayout.CENTER); 
56    
57           lblDescription = new JLabel("", SwingConstants.CENTER); 
58           lblValue = new JLabel(df.format(sliderMin)); 
59           pnlLabels = new JPanel(new GridLayout(0, 1)); 
60           pnlLabels.add(lblDescription); 
61           pnlLabels.add(lblValue); 
62           add(pnlLabels, BorderLayout.SOUTH); 
63           sliderPosition.setValue(intToDouble(JSLIDER_MIN)); 
64       } 
65    
66       /** 
67        * Construct a ObservableSlider ranging from min to max. 
68        * 
69        * @param min The minimum value of the slider 
70        * @param max The maximum value of the slider 
71        */ 
72       public ObservableSlider(final float min, final float max) { 
73           this(); 
74           setMinimum(min); 
75           setMaximum(max); 
76       } 
77    
78       /** 
79        * Set the text of the label. 
80        * 
81        * @param s The string which will appear below the slider. 
82        */ 
83       public void setLabel(final String s) { 
84           lblDescription.setText(s); 
85       } 
86    
87       /** 
88        * Set the label of a tick 
89        * 
90        * @param value The tick at which the label will appear. 
91        * @param label The text of the label. 
92        */ 
93       public void setTickLabel(final float value, final String label) { 
94           hshLabelTable.put(new Integer(doubleToInt(value)), new JLabel(label)); 
95           js.setLabelTable(hshLabelTable); 
96           js.setPaintLabels(true); 
97       } 
98    
99       /** 
100       * Get the minimum value of the slider. 
101       * 
102       * @return Minimum slider value 
103       */ 
104      public float getMinimum() { 
105          return sliderMin; 
106      } 
107   
108      /** 
109       * Set the minimum value of the slider. 
110       * 
111       * @param newValue New minimum slider value 
112       */ 
113      public void setMinimum(final float newValue) { 
114          final float position; 
115          sliderMin = newValue; 
116          position = Math.max(sliderPosition.getValue(), newValue); 
117          js.setValue(doubleToInt(position)); 
118          sliderPosition.setValue(position); 
119          lblValue.setText(df.format(position)); 
120      } 
121   
122      /** 
123       * Get the maximum value of the slider. 
124       * 
125       * @return Maximum slider value 
126       */ 
127      public float getMaximum() { 
128          return sliderMax; 
129      } 
130   
131      /** 
132       * Set the maximum value of the slider. 
133       * 
134       * @param newValue New maximum slider value 
135       */ 
136      public void setMaximum(final float newValue) { 
137          final float position; 
138          sliderMax = newValue; 
139          position = Math.min(sliderPosition.getValue(), newValue); 
140          js.setValue(doubleToInt(position)); 
141          sliderPosition.setValue(position); 
142          lblValue.setText(df.format(position)); 
143      } 
144   
145      /** 
146       * Determine whether the slider has a log scale. 
147       * 
148       * @return True = log; false = linear 
149       */ 
150      public boolean isLogScale() { 
151          return isLogScale; 
152      } 
153   
154      /** 
155       * Set whether the slider has a log scale. 
156       * 
157       * @param state True = log; false = linear 
158       */ 
159      public void setLogScale(final boolean state) { 
160          isLogScale = state; 
161      } 
162   
163      /** 
164       * Get the current value of the slider. 
165       * 
166       * @return The floating point value of the slider. 
167       */ 
168      public float getValue() { 
169          return sliderPosition.getValue(); 
170      } 
171   
172      /** 
173       * Set the current value of the slider. 
174       * 
175       * @param newValue The new floating point position value. 
176       */ 
177      public void setValue(final float newValue) { 
178          js.setValue(doubleToInt(newValue)); 
179      } 
180   
181      /** 
182       * Change enabled/disabled state. 
183       * 
184       * @param state True = enabled, false = disabled 
185       */ 
186      public void setEnabled(final boolean state) { 
187          js.setEnabled(state); 
188          lblDescription.setEnabled(state); 
189          lblValue.setEnabled(state); 
190      } 
191   
192      /** 
193       * Add the specified Observer to the list of parties notified 
194       * if the slider is moved. 
195       * 
196       * @param o The Observer to be added. 
197       */ 
198      public void addObserver(final Observer o) { 
199          sliderPosition.addObserver(o); 
200      } 
201   
202      /** 
203       * Convert the integer index of the JSlider to a floating point 
204       * number in the user's specified range. 
205       * 
206       * @param in A position on the underlying JSlider. 
207       * @return The position in the user-specified range. 
208       */ 
209      private float intToDouble(final int in) { 
210          if (!isLogScale) { 
211              return sliderMin + (sliderMax - sliderMin) / (JSLIDER_MAX - JSLIDER_MIN) * 
212                      (in - JSLIDER_MIN); 
213          } else { 
214              return 0; 
215          } 
216      } 
217   
218      /** 
219       * Convert a floating point number in the user's specified range 
220       * to an integer index on the underlying JSlider. 
221       * 
222       * @param in A position in the user-specified range. 
223       * @return The position on the underlying JSlider. 
224       */ 
225      private int doubleToInt(final float in) { 
226          if (!isLogScale) { 
227              return JSLIDER_MIN + (int) (((float) JSLIDER_MAX - JSLIDER_MIN) 
228                      / (sliderMax - sliderMin) * (in - sliderMin)); 
229          } else { 
230              return 0; 
231          } 
232      } 
233  }