001: package JSci.swing;
002:
003: import java.awt.*;
004: import java.awt.event.*;
005: import java.awt.geom.*;
006: import java.util.*;
007: import javax.swing.*;
008: import javax.swing.event.*;
009:
010: /** A pointer for the JRoundDial or JArcDial */
011: public class JPointer {
012:
013: private double s;
014: private int type;
015: private Shape shape = null;
016: private Color color = Color.BLACK;
017: private boolean enabled = true;
018: private boolean adjusting = false;
019:
020: /**
021: * @param t the type of the pointer
022: */
023: public JPointer(int t) {
024: s = 0.0;
025: type = t;
026: }
027:
028: /** get the value of the pointer
029: * @return the value
030: */
031: public double getValue() {
032: return s;
033: }
034:
035: /** set the value of the pointer
036: * @param v the value
037: */
038: public void setValue(double v) {
039: if (s == v)
040: return;
041: s = v;
042: if (!adjusting)
043: fireStateChanged();
044: }
045:
046: /** enable or disable the motion by the mouse
047: * @param b should the mouse move the pointer?
048: */
049: public void setEnabled(boolean b) {
050: enabled = b;
051: }
052:
053: /** If you are adjusting the value, the changes should not be fired
054: * (dispatched) to the listeners. Typically, when the movement is done by
055: * the mouse, only releasing the button actually fires the change.
056: * If appropriate, this fires the state changed.
057: * @param b are the following movements adjustments?
058: */
059: public void setAdjusting(boolean b) {
060: if (adjusting && !b)
061: fireStateChanged();
062: adjusting = b;
063: }
064:
065: /** set the color of the pointer
066: * @param col the desired color
067: */
068: public void setColor(Color col) {
069: color = col;
070: }
071:
072: /** check if a point is inside the pointer image
073: * @param p the point
074: * @return is p inside the pointer image
075: */
076: public boolean contains(Point p) {
077: return shape.contains(p) && enabled;
078: }
079:
080: /** draw the pointer on the dial. Called by the dials.
081: * @param g the graphics on which to draw
082: * @param radius the radius of the dial
083: * @param one the value of one turn
084: * @param zero the angle (clockwise, starting from the top) at which the zero should
085: * be placed
086: * @param x0 horizontal coordinate of the center of the dial
087: * @param y0 vertical coordinate of the center of the dial
088: */
089: protected void paintOnDial(Graphics2D g, double radius, double one,
090: double zero, double x0, double y0) {
091: AffineTransform at = AffineTransform.getTranslateInstance(x0,
092: y0);
093: at.scale(radius / 1000.0, radius / 1000.0);
094: at.rotate(2.0 * Math.PI * getValue() / one + zero);
095: switch (type) {
096: case POINTER_SIMPLE_TRIANGLE:
097: g.setColor(color);
098: shape = at
099: .createTransformedShape(POINTER_SHAPE_SIMPLE_TRIANGLE);
100: g.fill(shape);
101: break;
102: case POINTER_SIMPLE_QUADRANGLE:
103: g.setColor(color);
104: shape = at
105: .createTransformedShape(POINTER_SHAPE_SIMPLE_QUADRANGLE);
106: g.fill(shape);
107: break;
108: case POINTER_SIMPLE_STOP:
109: g.setColor(color);
110: shape = at
111: .createTransformedShape(POINTER_SHAPE_SIMPLE_STOP);
112: g.fill(shape);
113: break;
114: }
115: }
116:
117: /** draw the slider on the dial. Called by the dials.
118: * @param g the graphics on which to draw
119: * @param start the value on the bottom of the JSliderPlus
120: * @param end the value on the top of the JSliderPlus
121: * @param width the width of the component
122: * @param heigth the heigth of the component
123: */
124: protected void paintOnSlider(Graphics2D g, double start,
125: double end, double width, double heigth) {
126: AffineTransform at = AffineTransform.getTranslateInstance(
127: width / 2.0, heigth
128: * (0.9 - 0.8 * (s - start) / (end - start)));
129: at.scale(width / 1000.0, heigth / 2000.0);
130: switch (type) {
131: case SLIDER_SIMPLE_TRIANGLE:
132: g.setColor(color);
133: shape = at
134: .createTransformedShape(SLIDER_SHAPE_SIMPLE_TRIANGLE);
135: g.fill(shape);
136: break;
137: case SLIDER_SIMPLE_QUADRANGLE:
138: g.setColor(color);
139: shape = at
140: .createTransformedShape(SLIDER_SHAPE_SIMPLE_QUADRANGLE);
141: g.fill(shape);
142: break;
143: case SLIDER_SIMPLE_STOP:
144: g.setColor(color);
145: shape = at.createTransformedShape(SLIDER_SHAPE_SIMPLE_STOP);
146: g.fill(shape);
147: break;
148: }
149: }
150:
151: // EVENTS HANDLING
152:
153: /**
154: * Only one ChangeEvent is needed per model instance since the
155: * event's only (read-only) state is the source property. The source
156: * of events generated here is always "this".
157: */
158: private transient ChangeEvent changeEvent = null;
159:
160: /**
161: * The list of ChangeListeners for this model. Subclasses may
162: * store their own listeners here.
163: */
164: protected EventListenerList listenerList = new EventListenerList();
165:
166: /**
167: * Adds a ChangeListener to the model's listener list. The
168: * ChangeListeners must be notified when the models value changes.
169: *
170: * @param l the ChangeListener to add
171: * @see #removeChangeListener
172: */
173: public void addChangeListener(ChangeListener l) {
174: listenerList.add(ChangeListener.class, l);
175: }
176:
177: /**
178: * Removes a ChangeListener from the model's listener list.
179: *
180: * @param l the ChangeListener to remove
181: * @see #addChangeListener
182: */
183: public void removeChangeListener(ChangeListener l) {
184: listenerList.remove(ChangeListener.class, l);
185: }
186:
187: /**
188: * Returns an array of all the <code>ChangeListener</code>s added
189: * to this JPointer with addChangeListener().
190: *
191: * @return all of the <code>ChangeListener</code>s added or an empty
192: * array if no listeners have been added
193: */
194: public ChangeListener[] getChangeListeners() {
195: return (ChangeListener[]) listenerList
196: .getListeners(ChangeListener.class);
197: }
198:
199: /**
200: * Run each ChangeListeners stateChanged() method.
201: *
202: * @see #setValue
203: * @see EventListenerList
204: */
205: protected void fireStateChanged() {
206: Object[] listeners = listenerList.getListenerList();
207: for (int i = listeners.length - 2; i >= 0; i -= 2) {
208: if (listeners[i] == ChangeListener.class) {
209: if (changeEvent == null) {
210: changeEvent = new ChangeEvent(this );
211: }
212: ((ChangeListener) listeners[i + 1])
213: .stateChanged(changeEvent);
214: }
215: }
216: }
217:
218: /**
219: * Return an array of all the listeners of the given type that
220: * were added to this model. For example to find all of the
221: * ChangeListeners added to this model:
222: * <pre>
223: * myJPointer.getListeners(ChangeListener.class);
224: * </pre>
225: *
226: * @param listenerType the type of listeners to return, e.g. ChangeListener.class
227: * @return all of the objects receiving <em>listenerType</em> notifications
228: * from this model
229: */
230: public EventListener[] getListeners(Class listenerType) {
231: return listenerList.getListeners(listenerType);
232: }
233:
234: // POINTER TYPES AND SHAPES
235:
236: public static final int POINTER_SIMPLE_TRIANGLE = 0;
237: public static final int POINTER_SIMPLE_QUADRANGLE = 1;
238: public static final int POINTER_SIMPLE_STOP = 2;
239:
240: private static final Shape POINTER_SHAPE_SIMPLE_TRIANGLE;
241: private static final Shape POINTER_SHAPE_SIMPLE_QUADRANGLE;
242: private static final Shape POINTER_SHAPE_SIMPLE_STOP;
243:
244: static {
245: POINTER_SHAPE_SIMPLE_TRIANGLE = new Polygon(new int[] { -100,
246: 100, 00 }, new int[] { 100, 100, -600 }, 3);
247: POINTER_SHAPE_SIMPLE_QUADRANGLE = new Polygon(new int[] { -100,
248: 0, 100, 00 }, new int[] { 0, 100, 0, -600 }, 4);
249: int[] x = new int[16];
250: int[] y = new int[16];
251: for (int j = 0; j < 16; j++) {
252: x[j] = (int) (30 * Math.cos(2.0 * Math.PI * j / 16));
253: y[j] = (int) (-595 + 30 * Math.sin(2.0 * Math.PI * j / 16));
254: }
255: POINTER_SHAPE_SIMPLE_STOP = new Polygon(x, y, 16);
256: }
257:
258: // SLIDER TYPES AND SHAPES
259:
260: public static final int SLIDER_SIMPLE_TRIANGLE = 3;
261: public static final int SLIDER_SIMPLE_QUADRANGLE = 4;
262: public static final int SLIDER_SIMPLE_STOP = 5;
263:
264: private static final Shape SLIDER_SHAPE_SIMPLE_TRIANGLE;
265: private static final Shape SLIDER_SHAPE_SIMPLE_QUADRANGLE;
266: private static final Shape SLIDER_SHAPE_SIMPLE_STOP;
267:
268: static {
269: SLIDER_SHAPE_SIMPLE_TRIANGLE = new Polygon(new int[] { 100, 0,
270: 100 }, new int[] { -100, 0, 100 }, 3);
271: SLIDER_SHAPE_SIMPLE_QUADRANGLE = new Polygon(new int[] { 100,
272: 0, 100, 50 }, new int[] { -100, 0, 100, 0 }, 4);
273: int[] x = new int[16];
274: int[] y = new int[16];
275: for (int j = 0; j < 16; j++) {
276: x[j] = (int) (200 + 30 * Math.cos(2.0 * Math.PI * j / 16));
277: y[j] = (int) (30 * Math.sin(2.0 * Math.PI * j / 16));
278: }
279: SLIDER_SHAPE_SIMPLE_STOP = new Polygon(x, y, 16);
280: }
281:
282: }
|