KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mc4j > console > swing > LogarithmicJSlider


1 /*
2  * Copyright 2002-2004 Greg Hinkle
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.mc4j.console.swing;
18
19 import java.awt.Color JavaDoc;
20 import java.awt.Graphics JavaDoc;
21 import java.awt.Rectangle JavaDoc;
22 import java.beans.PropertyChangeEvent JavaDoc;
23 import java.beans.PropertyChangeListener JavaDoc;
24 import java.util.Enumeration JavaDoc;
25 import java.util.Hashtable JavaDoc;
26
27 import javax.swing.BoundedRangeModel JavaDoc;
28 import javax.swing.BoxLayout JavaDoc;
29 import javax.swing.JFrame JavaDoc;
30 import javax.swing.JLabel JavaDoc;
31 import javax.swing.JSlider JavaDoc;
32 import javax.swing.event.ChangeEvent JavaDoc;
33 import javax.swing.event.ChangeListener JavaDoc;
34 import javax.swing.plaf.SliderUI JavaDoc;
35 import javax.swing.plaf.UIResource JavaDoc;
36 import javax.swing.plaf.basic.BasicSliderUI JavaDoc;
37
38 /**
39  * This JSlider subclass uses a custom UI to allow a slider to work in
40  * logarithmic scale. Major and minor ticks are drawn for logarithmic
41  * scale as well.
42  *
43  * @author Greg Hinkle (ghinkle@users.sourceforge.net), Apr 10, 2004
44  * @version $Revision: 480 $($Author: ghinkl $ / $Date: 2004-10-05 01:17:41 -0400 (Tue, 05 Oct 2004) $)
45  */

46 public class LogarithmicJSlider extends JSlider JavaDoc {
47
48
49     public LogarithmicJSlider(int orientation) {
50         super(orientation);
51         SliderUI JavaDoc ui = new LogSliderUI(this);
52         this.setUI(ui);
53     }
54
55     public LogarithmicJSlider(int min, int max) {
56         super(min, max);
57         SliderUI JavaDoc ui = new LogSliderUI(this);
58         this.setUI(ui);
59     }
60
61     public LogarithmicJSlider(int min, int max, int value) {
62         super(min, max, value);
63         SliderUI JavaDoc ui = new LogSliderUI(this);
64         this.setUI(ui);
65     }
66
67     public LogarithmicJSlider(int orientation, int min, int max, int value) {
68         super(orientation, min, max, value);
69         SliderUI JavaDoc ui = new LogSliderUI(this);
70         this.setUI(ui);
71     }
72
73     public LogarithmicJSlider(BoundedRangeModel JavaDoc brm) {
74         super(brm);
75         SliderUI JavaDoc ui = new LogSliderUI(this);
76         this.setUI(ui);
77     }
78
79     public LogarithmicJSlider() {
80         SliderUI JavaDoc ui = new LogSliderUI(this);
81         this.setUI(ui);
82     }
83
84
85     public static class LogSliderUI extends BasicSliderUI JavaDoc {
86
87         public LogSliderUI(JSlider JavaDoc b) {
88             super(b);
89         }
90
91
92         public int xPositionForValue(int value) {
93             int min = slider.getMinimum();
94             int max = slider.getMaximum();
95             int trackLength = trackRect.width;
96             double valueRange = (double) Math.log(max) - (double) Math.log(min);
97             double pixelsPerValue = (double) trackLength / valueRange;
98             int trackLeft = trackRect.x;
99             int trackRight = trackRect.x + (trackRect.width - 1);
100             int xPosition;
101
102             if (!drawInverted()) {
103                 xPosition = trackLeft;
104                 xPosition += Math.round(pixelsPerValue * ((double) Math.log(value) - Math.log(min)));
105             } else {
106                 xPosition = trackRight;
107                 xPosition -= Math.round(pixelsPerValue * ((double) Math.log(value) - Math.log(min)));
108             }
109
110             xPosition = Math.max(trackLeft, xPosition);
111             xPosition = Math.min(trackRight, xPosition);
112
113             return xPosition;
114
115
116         }
117
118         public int yPositionForValue(int value) {
119             // TODO GH: Implement to support vertical log sliders
120
return super.yPositionForValue(value);
121         }
122
123         public int valueForYPosition(int yPos) {
124             // TODO GH: Implement to support vertical log sliders
125
return super.valueForYPosition(yPos);
126         }
127
128         public int valueForXPosition(int xPos) {
129             int value;
130             final int minValue = slider.getMinimum();
131             final int maxValue = slider.getMaximum();
132             final int trackLength = trackRect.width;
133             final int trackLeft = trackRect.x;
134             final int trackRight = trackRect.x + (trackRect.width - 1);
135
136             if (xPos <= trackLeft) {
137                 value = drawInverted() ? maxValue : minValue;
138             } else if (xPos >= trackRight) {
139                 value = drawInverted() ? minValue : maxValue;
140             } else {
141                 int distanceFromTrackLeft = xPos - trackLeft;
142                 double valueRange = (double) Math.log(maxValue) - (double) Math.log(minValue);
143                 //double valuePerPixel = (double)valueRange / (double)trackLength;
144
//int valueFromTrackLeft =
145
// (int)Math.round( Math.pow(3.5,(double)distanceFromTrackLeft * (double)valuePerPixel));
146

147                 int valueFromTrackLeft =
148                     (int)
149                     Math.round(Math.pow(Math.E, Math.log(minValue) + ((((double) distanceFromTrackLeft) * valueRange) / (double) trackLength)));
150
151                 value = drawInverted() ? maxValue - valueFromTrackLeft :
152                     (int) Math.log(minValue) + valueFromTrackLeft;
153             }
154
155             return value;
156
157         }
158
159         public void paintTicks(Graphics JavaDoc g) {
160             Rectangle JavaDoc tickBounds = tickRect;
161             int i;
162             int maj, min, max;
163             int w = tickBounds.width;
164             int h = tickBounds.height;
165             int centerEffect, tickHeight;
166
167             g.setColor(Color.black);
168
169             maj = slider.getMajorTickSpacing();
170             min = slider.getMinorTickSpacing();
171
172             if (slider.getOrientation() == JSlider.HORIZONTAL) {
173                 g.translate(0, tickBounds.y);
174
175                 int value = slider.getMinimum();
176                 int xPos = 0;
177
178                 if (slider.getMinorTickSpacing() > 0) {
179                     int majorValue = slider.getMinimum();
180
181                     while (value <= slider.getMaximum()) {
182                         if (value >= majorValue) {
183                             value = majorValue;
184                             majorValue *= maj;
185                         }
186                         value += (majorValue / 10.0);
187
188                         xPos = xPositionForValue(value);
189                         paintMinorTickForHorizSlider(g, tickBounds, xPos);
190
191                     }
192                 }
193
194                 if (slider.getMajorTickSpacing() > 0) {
195                     value = slider.getMinimum();
196
197                     while (value <= slider.getMaximum()) {
198                         xPos = xPositionForValue(value);
199                         paintMajorTickForHorizSlider(g, tickBounds, xPos);
200                         value *= slider.getMajorTickSpacing();
201                     }
202                 }
203
204                 g.translate(0, -tickBounds.y);
205             } else {
206
207                 g.translate(tickBounds.x, 0);
208
209                 int value = slider.getMinimum();
210                 int yPos = 0;
211
212                 if (slider.getMinorTickSpacing() > 0) {
213                     int majorValue = slider.getMinimum();
214                     int offset = 0;
215                     if (!slider.getComponentOrientation().isLeftToRight()) {
216                         offset = tickBounds.width - tickBounds.width / 2;
217                         g.translate(offset, 0);
218                     }
219
220                     while (value <= slider.getMaximum()) {
221                         if (value >= majorValue) {
222                             value = majorValue;
223                             majorValue *= maj;
224                         }
225
226                         yPos = yPositionForValue(value);
227                         paintMinorTickForVertSlider(g, tickBounds, yPos);
228                         value += (majorValue / 10.0);
229                     }
230
231                     if (!slider.getComponentOrientation().isLeftToRight()) {
232                         g.translate(-offset, 0);
233                     }
234                 }
235
236                 if (slider.getMajorTickSpacing() > 0) {
237                     value = slider.getMinimum();
238                     if (!slider.getComponentOrientation().isLeftToRight()) {
239                         g.translate(2, 0);
240                     }
241
242                     while (value <= slider.getMaximum()) {
243                         yPos = yPositionForValue(value);
244                         paintMajorTickForVertSlider(g, tickBounds, yPos);
245                         value *= slider.getMajorTickSpacing();
246                     }
247
248                     if (!slider.getComponentOrientation().isLeftToRight()) {
249                         g.translate(-2, 0);
250                     }
251                 }
252                 g.translate(-tickBounds.x, 0);
253             }
254         }
255
256     }
257
258
259     public static void main(String JavaDoc[] args) {
260         JFrame JavaDoc frame = new JFrame JavaDoc();
261         frame.setSize(408, 408);
262
263         final JSlider JavaDoc slider = new LogarithmicJSlider(100, 10000000, 1000);
264         final JLabel JavaDoc label = new JLabel JavaDoc();
265
266         slider.setPaintTicks(true);
267         slider.setPaintLabels(true);
268         slider.setMajorTickSpacing(10);
269         slider.setMinorTickSpacing(10);
270
271         slider.addChangeListener(new ChangeListener JavaDoc() {
272             public void stateChanged(ChangeEvent JavaDoc e) {
273                 System.out.println("Value is now: " + slider.getValue());
274
275
276                 label.setText("Current value is: " + slider.getValue());
277
278             }
279         });
280
281         frame.getContentPane().setLayout(new BoxLayout JavaDoc(frame.getContentPane(), BoxLayout.Y_AXIS));
282         frame.getContentPane().add(slider);
283         frame.getContentPane().add(label);
284         frame.setVisible(true);
285
286         LogSliderUI ui = (LogSliderUI) slider.getUI();
287         for (int i = 10; i <= 100000; i *= 10) {
288             System.out.println("I: " + i + " xPos: " + ui.xPositionForValue(i) + " valueFor: " + ui.valueForXPosition(ui.xPositionForValue(i)));
289         }
290
291     }
292
293
294     /**
295      * Creates a hashtable holding the text labels for this slider. This implementation
296      * uses the increment as a log-base.
297      *
298      */

299     public Hashtable JavaDoc createStandardLabels(int increment, int start) {
300         if (start > getMaximum() || start < getMinimum()) {
301             throw new IllegalArgumentException JavaDoc("Slider label start point out of range.");
302         }
303
304         if (increment <= 0) {
305             throw new IllegalArgumentException JavaDoc("Label incremement must be > 0");
306         }
307
308         class LabelHashtable extends Hashtable JavaDoc implements PropertyChangeListener JavaDoc {
309             int increment = 0;
310             int start = 0;
311             boolean startAtMin = false;
312
313
314             public LabelHashtable(int increment, int start) {
315                 super();
316                 this.increment = increment;
317                 this.start = start;
318                 startAtMin = start == getMinimum();
319                 createLabels(this, increment, start);
320             }
321
322             public void propertyChange(PropertyChangeEvent JavaDoc e) {
323                 if (e.getPropertyName().equals("minimum") && startAtMin) {
324                     start = getMinimum();
325                 }
326
327                 if (e.getPropertyName().equals("minimum") ||
328                     e.getPropertyName().equals("maximum")) {
329
330                     Enumeration JavaDoc keys = getLabelTable().keys();
331                     Object JavaDoc key = null;
332                     Hashtable JavaDoc hashtable = new Hashtable JavaDoc();
333
334                     // Save the labels that were added by the developer
335
while (keys.hasMoreElements()) {
336                         key = keys.nextElement();
337                         Object JavaDoc value = getLabelTable().get(key);
338                         if (!(value instanceof LabelUIResource)) {
339                             hashtable.put(key, value);
340                         }
341                     }
342
343                     clear();
344                     createLabels(this, increment, start);
345
346                     // Add the saved labels
347
keys = hashtable.keys();
348                     while (keys.hasMoreElements()) {
349                         key = keys.nextElement();
350                         put(key, hashtable.get(key));
351                     }
352                     ((JSlider JavaDoc) e.getSource()).setLabelTable(this);
353                 }
354             }
355         }
356
357         LabelHashtable table = new LabelHashtable(increment, start);
358
359         if (getLabelTable() != null && (getLabelTable() instanceof PropertyChangeListener JavaDoc)) {
360             removePropertyChangeListener((PropertyChangeListener JavaDoc) getLabelTable());
361         }
362
363         addPropertyChangeListener(table);
364
365         return table;
366     }
367
368     /**
369      * This method creates the table of labels that are used to label major ticks
370      * on the slider.
371      * @param table
372      * @param increment
373      * @param start
374      */

375     protected void createLabels(Hashtable JavaDoc table, int increment, int start) {
376         for (int labelIndex = start; labelIndex <= getMaximum(); labelIndex *= increment) {
377
378             table.put(new Integer JavaDoc(labelIndex), new LabelUIResource("" + labelIndex, JLabel.CENTER));
379         }
380     }
381
382     protected class LabelUIResource extends JLabel JavaDoc implements UIResource JavaDoc {
383         public LabelUIResource(String JavaDoc text, int alignment) {
384             super(text, alignment);
385             setName("Slider.label");
386         }
387     }
388
389 }
390
Popular Tags