Subversion Repositories svn.mios

Rev

Rev 213 | Rev 657 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 213 Rev 628
1
/*
1
/*
2
 * @(#)Knob.java    beta7   2006/04/23
2
 * @(#)Knob.java    beta8   2006/04/23
3
 *
3
 *
4
 * Copyright (C) 2006    Adam King (adamjking@optusnet.com.au)
4
 * Copyright (C) 2008    Adam King (adamjking@optusnet.com.au)
5
 *
5
 *
6
 * This application is free software; you can redistribute it and/or modify
6
 * This application is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
9
 * (at your option) any later version.
10
 *
10
 *
11
 * This application is distributed in the hope that it will be useful,
11
 * This application is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
14
 * GNU General Public License for more details.
15
 *
15
 *
16
 * You should have received a copy of the GNU General Public License
16
 * You should have received a copy of the GNU General Public License
17
 * along with this application; if not, write to the Free Software
17
 * along with this application; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 *
19
 *
20
 ****************************************************************************
20
 ****************************************************************************
21
 * Based on com.dreamfabric.DKnob.java
21
 * Based on com.dreamfabric.DKnob.java
22
 * (c) 2000 by Joakim Eriksson
22
 * (c) 2000 by Joakim Eriksson
23
 ****************************************************************************
23
 ****************************************************************************
24
 */
24
 */
25
25
26
package org.midibox.utils.gui;
26
package org.midibox.utils.gui;
27
27
28
import java.awt.BasicStroke;
28
import java.awt.BasicStroke;
29
import java.awt.Color;
29
import java.awt.Color;
30
import java.awt.Dimension;
30
import java.awt.Dimension;
31
import java.awt.Graphics;
31
import java.awt.Graphics;
32
import java.awt.Graphics2D;
32
import java.awt.Graphics2D;
33
import java.awt.event.FocusEvent;
33
import java.awt.event.FocusEvent;
34
import java.awt.event.FocusListener;
34
import java.awt.event.FocusListener;
35
import java.awt.event.KeyEvent;
35
import java.awt.event.KeyEvent;
36
import java.awt.event.KeyListener;
36
import java.awt.event.KeyListener;
37
import java.awt.event.MouseEvent;
37
import java.awt.event.MouseEvent;
38
import java.awt.event.MouseListener;
38
import java.awt.event.MouseListener;
39
import java.awt.event.MouseMotionListener;
39
import java.awt.event.MouseMotionListener;
40
import java.awt.geom.Arc2D;
40
import java.awt.geom.Arc2D;
41
41
42
import javax.swing.Icon;
42
import javax.swing.Icon;
43
import javax.swing.ImageIcon;
43
import javax.swing.ImageIcon;
44
import javax.swing.JComponent;
44
import javax.swing.JComponent;
45
import javax.swing.UIManager;
45
import javax.swing.UIManager;
46
import javax.swing.event.ChangeEvent;
46
import javax.swing.event.ChangeEvent;
47
import javax.swing.event.ChangeListener;
47
import javax.swing.event.ChangeListener;
48
import javax.swing.event.EventListenerList;
48
import javax.swing.event.EventListenerList;
49
49
50
public class Knob extends JComponent implements MouseListener,
50
public class Knob extends JComponent implements MouseListener,
51
        MouseMotionListener, KeyListener, FocusListener {
51
        MouseMotionListener, KeyListener, FocusListener {
52
52
53
    public final static int LINEAR = 0;
53
    public final static int LINEAR = 0;
54
54
55
    public final static int ROUND = 1;
55
    public final static int ROUND = 1;
56
56
57
    public static int mouseDragType = LINEAR;
57
    public static int mouseDragType = LINEAR;
58
58
59
    private Icon icon;
59
    private Icon icon;
60
60
61
    private final static float START = 225;
61
    private final static float START = 225;
62
62
63
    private final static float LENGTH = 270;
63
    private final static float LENGTH = 270;
64
64
65
    private final static float START_ANG = (START / 360) * (float) Math.PI * 2;
65
    private final static float START_ANG = (START / 360) * (float) Math.PI * 2;
66
66
67
    private final static float LENGTH_ANG = (LENGTH / 360) * (float) Math.PI
67
    private final static float LENGTH_ANG = (LENGTH / 360) * (float) Math.PI
68
            * 2;
68
            * 2;
69
69
70
    private final static float LENGTH_ANG_DIV10 = (float) (LENGTH_ANG / 10.01);
70
    private final static float LENGTH_ANG_DIV10 = (float) (LENGTH_ANG / 10.01);
71
71
72
    private final static float MULTIP = 180 / (float) Math.PI;
72
    private final static float MULTIP = 180 / (float) Math.PI;
73
73
74
    private final static Color FOCUS_COLOR = UIManager.getColor("Slider.focus");
74
    private final static Color FOCUS_COLOR = UIManager.getColor("Slider.focus");
75
75
76
    private float DRAG_SPEED;
76
    private float DRAG_SPEED;
77
77
78
    private float CLICK_SPEED;
78
    private float CLICK_SPEED;
79
79
80
    private static Dimension PREF_SIZE;
80
    private static Dimension PREF_SIZE;
81
81
82
    private int middle;
82
    private int middle;
83
83
84
    private ChangeEvent changeEvent = null;
84
    private ChangeEvent changeEvent = null;
85
85
86
    private EventListenerList listenerList = new EventListenerList();
86
    private EventListenerList listenerList = new EventListenerList();
87
87
88
    private Arc2D hitArc = new Arc2D.Float(Arc2D.PIE);
88
    private Arc2D hitArc = new Arc2D.Float(Arc2D.PIE);
89
89
90
    private float ang = START_ANG;
90
    private float ang = START_ANG;
91
91
92
    private float minValue = 0f;
92
    private float minValue = 0f;
93
93
94
    private float maxValue = 1.0f;
94
    private float maxValue = 1.0f;
95
95
96
    private float value;
96
    private float value;
97
97
98
    private int dragpos = -1;
98
    private int dragpos = -1;
99
99
100
    private float startVal;
100
    private float startVal;
101
101
102
    private double lastAng;
102
    private double lastAng;
103
103
104
    private Color tickColor;
104
    private Color tickColor;
105
105
106
    public Knob(ImageIcon icon) {
106
    public Knob(ImageIcon icon) {
107
107
108
        this.icon = icon;
108
        this.icon = icon;
109
109
110
        PREF_SIZE = new Dimension(icon.getIconHeight() + 8, icon
110
        PREF_SIZE = new Dimension(icon.getIconHeight() + 8, icon
111
                .getIconHeight() + 8);
111
                .getIconHeight() + 8);
112
        DRAG_SPEED = 0.0075F;// 0.01F;
112
        DRAG_SPEED = 0.0075F;// 0.01F;
113
        CLICK_SPEED = 0.004F;
113
        CLICK_SPEED = 0.01F;
114
114
115
        hitArc.setAngleStart(235); // Degrees ??? Radians???
115
        hitArc.setAngleStart(235); // Degrees ??? Radians???
116
        hitArc.setFrame(4, 4, icon.getIconHeight(), icon.getIconHeight());
116
        hitArc.setFrame(4, 4, icon.getIconHeight(), icon.getIconHeight());
117
        middle = getHeight() / 2;
117
        middle = getHeight() / 2;
118
118
119
        addMouseListener(this);
119
        addMouseListener(this);
120
        addMouseMotionListener(this);
120
        addMouseMotionListener(this);
121
        addKeyListener(this);
121
        addKeyListener(this);
122
        addFocusListener(this);
122
        addFocusListener(this);
123
    }
123
    }
124
124
125
    public boolean isFocusable() {
125
    public boolean isFocusable() {
126
        return true;
126
        return true;
127
    }
127
    }
128
128
129
    private void incValue() {
129
    private void incValue() {
130
        setValue(value + CLICK_SPEED);
130
        setValue(value + CLICK_SPEED);
131
    }
131
    }
132
132
133
    private void decValue() {
133
    private void decValue() {
134
        setValue(value - CLICK_SPEED);
134
        setValue(value - CLICK_SPEED);
135
    }
135
    }
136
136
137
    public float getMaxValue() {
137
    public float getMaxValue() {
138
        return maxValue;
138
        return maxValue;
139
    }
139
    }
140
140
141
    public void setMaxValue(float maxValue) {
141
    public void setMaxValue(float maxValue) {
142
        this.maxValue = maxValue;
142
        this.maxValue = maxValue;
143
    }
143
    }
144
144
145
    public float getMinValue() {
145
    public float getMinValue() {
146
        return minValue;
146
        return minValue;
147
    }
147
    }
148
148
149
    public void setMinValue(float minValue) {
149
    public void setMinValue(float minValue) {
150
        this.minValue = minValue;
150
        this.minValue = minValue;
151
    }
151
    }
152
152
153
    public float getValue() {
153
    public float getValue() {
154
        return value;
154
        return value;
155
    }
155
    }
156
156
157
    public void setValue(float val) {
157
    public void setValue(float val) {
158
        if (val < 0)
158
        if (val < 0)
159
            val = 0;
159
            val = 0;
160
        if (val > 1)
160
        if (val > 1)
161
            val = 1;
161
            val = 1;
162
        float oldVal = this.value;
162
        float oldVal = this.value;
163
        this.value = val;
163
        this.value = val;
164
        ang = START_ANG - LENGTH_ANG * val;
164
        ang = START_ANG - LENGTH_ANG * val;
165
        repaint();
165
        repaint();
166
        if (oldVal != this.value) {
166
        if (oldVal != this.value) {
167
            fireChangeEvent();
167
            fireChangeEvent();
168
        }
168
        }
169
    }
169
    }
170
170
171
    public void addChangeListener(ChangeListener cl) {
171
    public void addChangeListener(ChangeListener cl) {
172
        listenerList.add(ChangeListener.class, cl);
172
        listenerList.add(ChangeListener.class, cl);
173
    }
173
    }
174
174
175
    public void removeChangeListener(ChangeListener cl) {
175
    public void removeChangeListener(ChangeListener cl) {
176
        listenerList.remove(ChangeListener.class, cl);
176
        listenerList.remove(ChangeListener.class, cl);
177
    }
177
    }
178
178
179
    public Dimension getMinimumSize() {
179
    public Dimension getMinimumSize() {
180
        return PREF_SIZE;
180
        return PREF_SIZE;
181
    }
181
    }
182
182
183
    public Dimension getPreferredSize() {
183
    public Dimension getPreferredSize() {
184
        return PREF_SIZE;
184
        return PREF_SIZE;
185
    }
185
    }
186
186
187
    public void setTickColor(Color tickColor) {
187
    public void setTickColor(Color tickColor) {
188
        this.tickColor = tickColor;
188
        this.tickColor = tickColor;
189
        repaint();
189
        repaint();
190
    }
190
    }
191
191
192
    protected void fireChangeEvent() {
192
    protected void fireChangeEvent() {
193
        Object[] listeners = listenerList.getListenerList();
193
        Object[] listeners = listenerList.getListenerList();
194
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
194
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
195
            if (listeners[i] == ChangeListener.class) {
195
            if (listeners[i] == ChangeListener.class) {
196
                if (changeEvent == null)
196
                if (changeEvent == null)
197
                    changeEvent = new ChangeEvent(this);
197
                    changeEvent = new ChangeEvent(this);
198
                ((ChangeListener) listeners[i + 1]).stateChanged(changeEvent);
198
                ((ChangeListener) listeners[i + 1]).stateChanged(changeEvent);
199
            }
199
            }
200
        }
200
        }
201
    }
201
    }
202
202
203
    public void paint(Graphics g) {
203
    public void paint(Graphics g) {
204
204
205
        if (hasFocus()) {
205
        if (hasFocus()) {
206
            paintFocus(g);
206
            paintFocus(g);
207
        }
207
        }
208
208
209
        paintTicks(g);
209
        paintTicks(g);
210
        paintKnob(g);
210
        paintKnob(g);
211
    }
211
    }
212
212
213
    public void paintFocus(Graphics g) {
213
    public void paintFocus(Graphics g) {
214
214
215
        g.setColor(FOCUS_COLOR);
215
        g.setColor(FOCUS_COLOR);
216
        Graphics2D g2d = (Graphics2D) g;
216
        Graphics2D g2d = (Graphics2D) g;
217
217
218
        g2d.setStroke(new BasicStroke(1f, BasicStroke.CAP_BUTT,
218
        g2d.setStroke(new BasicStroke(1f, BasicStroke.CAP_BUTT,
219
                BasicStroke.JOIN_ROUND, 1f, new float[] { 1f }, 0f));
219
                BasicStroke.JOIN_ROUND, 1f, new float[] { 1f }, 0f));
220
220
221
        int width = getWidth();
221
        int width = getWidth();
222
        int height = getHeight();
222
        int height = getHeight();
223
223
224
        g2d.drawLine(0, 0, width, 0);
224
        g2d.drawLine(0, 0, width, 0);
225
        g2d.drawLine(width - 1, 0, width - 1, height);
225
        g2d.drawLine(width - 1, 0, width - 1, height);
226
        g2d.drawLine(0, height - 1, width, height - 1);
226
        g2d.drawLine(0, height - 1, width, height - 1);
227
        g2d.drawLine(0, 0, 0, height);
227
        g2d.drawLine(0, 0, 0, height);
228
228
229
        g2d.setStroke(new BasicStroke());
229
        g2d.setStroke(new BasicStroke());
230
        g2d.setColor(Color.BLACK);
230
        g2d.setColor(Color.BLACK);
231
    }
231
    }
232
232
233
    public void paintTicks(Graphics g) {
233
    public void paintTicks(Graphics g) {
234
        g.setColor(tickColor);
234
        g.setColor(tickColor);
235
235
236
        int offsetX = ((getWidth()) - icon.getIconHeight()) / 2;
236
        int offsetX = ((getWidth()) - icon.getIconHeight()) / 2;
237
        int offsetY = ((getHeight()) - icon.getIconHeight()) / 2;
237
        int offsetY = ((getHeight()) - icon.getIconHeight()) / 2;
238
238
239
        for (float a2 = START_ANG; a2 >= START_ANG - LENGTH_ANG; a2 = a2
239
        for (float a2 = START_ANG; a2 >= START_ANG - LENGTH_ANG; a2 = a2
240
                - LENGTH_ANG_DIV10) {
240
                - LENGTH_ANG_DIV10) {
241
            int x = offsetX + (icon.getIconHeight() / 2)
241
            int x = offsetX + (icon.getIconHeight() / 2)
242
                    + (int) ((2 + (icon.getIconHeight() / 2)) * Math.cos(a2));
242
                    + (int) ((2 + (icon.getIconHeight() / 2)) * Math.cos(a2));
243
            int y = offsetY + (icon.getIconHeight() / 2)
243
            int y = offsetY + (icon.getIconHeight() / 2)
244
                    - (int) ((2 + (icon.getIconHeight() / 2)) * Math.sin(a2));
244
                    - (int) ((2 + (icon.getIconHeight() / 2)) * Math.sin(a2));
245
            g.drawLine(x, y, x, y);
245
            g.drawLine(x, y, x, y);
246
        }
246
        }
247
    }
247
    }
248
248
249
    public void paintKnob(Graphics g) {
249
    public void paintKnob(Graphics g) {
250
250
251
        Graphics2D g2d = (Graphics2D) g;
251
        Graphics2D g2d = (Graphics2D) g;
252
252
253
        int offsetX = ((getWidth()) - icon.getIconHeight()) / 2;
253
        int offsetX = ((getWidth()) - icon.getIconHeight()) / 2;
254
        int offsetY = ((getHeight()) - icon.getIconHeight()) / 2;
254
        int offsetY = ((getHeight()) - icon.getIconHeight()) / 2;
255
        int noImages = (icon.getIconWidth() / icon.getIconHeight()) - 1;
255
        int noImages = (icon.getIconWidth() / icon.getIconHeight()) - 1;
256
256
257
        if (icon != null) {
257
        if (icon != null) {
258
258
259
            g2d.clipRect(offsetX, offsetY, icon.getIconHeight(), icon
259
            g2d.clipRect(offsetX, offsetY, icon.getIconHeight(), icon
260
                    .getIconHeight());
260
                    .getIconHeight());
261
            offsetX -= icon.getIconHeight() * ((int) (value * noImages));
261
            offsetX -= icon.getIconHeight() * ((int) (value * noImages));
262
            icon.paintIcon(this, g2d, offsetX, offsetY);
262
            icon.paintIcon(this, g2d, offsetX, offsetY);
263
            g2d.dispose();
263
            g2d.dispose();
264
        }
264
        }
265
    }
265
    }
266
266
267
    public void mousePressed(MouseEvent me) {
267
    public void mousePressed(MouseEvent me) {
268
268
269
        dragpos = me.getX() - me.getY();
269
        dragpos = me.getX() - me.getY();
270
        startVal = value;
270
        startVal = value;
271
271
272
        // Fix last angle
272
        // Fix last angle
273
        int xpos = middle - me.getX();
273
        int xpos = middle - me.getX();
274
        int ypos = middle - me.getY();
274
        int ypos = middle - me.getY();
275
        lastAng = Math.atan2(xpos, ypos);
275
        lastAng = Math.atan2(xpos, ypos);
276
        requestFocus();
276
        requestFocus();
277
    }
277
    }
278
278
279
    public void mouseReleased(MouseEvent me) {
279
    public void mouseReleased(MouseEvent me) {
280
    }
280
    }
281
281
282
    public void mouseClicked(MouseEvent me) {
282
    public void mouseClicked(MouseEvent me) {
283
        hitArc.setAngleExtent(-(LENGTH + 20));
283
        hitArc.setAngleExtent(-(LENGTH + 20));
284
        if (hitArc.contains(me.getX(), me.getY())) {
284
        if (hitArc.contains(me.getX(), me.getY())) {
285
            hitArc.setAngleExtent(MULTIP * (ang - START_ANG) - 10);
285
            hitArc.setAngleExtent(MULTIP * (ang - START_ANG) - 10);
286
            if (hitArc.contains(me.getX(), me.getY())) {
286
            if (hitArc.contains(me.getX(), me.getY())) {
287
                decValue();
287
                decValue();
288
            } else
288
            } else
289
                incValue();
289
                incValue();
290
        }
290
        }
291
    }
291
    }
292
292
293
    public void mouseEntered(MouseEvent me) {
293
    public void mouseEntered(MouseEvent me) {
294
    }
294
    }
295
295
296
    public void mouseExited(MouseEvent me) {
296
    public void mouseExited(MouseEvent me) {
297
    }
297
    }
298
298
299
    public void mouseMoved(MouseEvent me) {
299
    public void mouseMoved(MouseEvent me) {
300
    }
300
    }
301
301
302
    public void mouseDragged(MouseEvent me) {
302
    public void mouseDragged(MouseEvent me) {
303
        if (mouseDragType == LINEAR) {
303
        if (mouseDragType == LINEAR) {
304
            float f = DRAG_SPEED * (float) ((me.getX() - me.getY()) - dragpos);
304
            float f = DRAG_SPEED * (float) ((me.getX() - me.getY()) - dragpos);
305
            setValue(startVal + f);
305
            setValue(startVal + f);
306
        }
306
        }
307
307
308
        else if (mouseDragType == ROUND) {
308
        else if (mouseDragType == ROUND) {
309
            int xpos = middle - me.getX();
309
            int xpos = middle - me.getX();
310
            int ypos = middle - me.getY();
310
            int ypos = middle - me.getY();
311
            double ang = Math.atan2(xpos, ypos);
311
            double ang = Math.atan2(xpos, ypos);
312
            double diff = lastAng - ang;
312
            double diff = lastAng - ang;
313
313
314
            setValue((float) (value + (diff / LENGTH_ANG)));
314
            setValue((float) (value + (diff / LENGTH_ANG)));
315
315
316
            lastAng = ang;
316
            lastAng = ang;
317
        }
317
        }
318
    }
318
    }
319
319
320
    public void keyPressed(KeyEvent e) {
320
    public void keyPressed(KeyEvent e) {
321
        int k = e.getKeyCode();
321
        int k = e.getKeyCode();
322
        if (k == KeyEvent.VK_RIGHT)
322
        if (k == KeyEvent.VK_RIGHT)
323
            incValue();
323
            incValue();
324
        else if (k == KeyEvent.VK_LEFT)
324
        else if (k == KeyEvent.VK_LEFT)
325
            decValue();
325
            decValue();
326
    }
326
    }
327
327
328
    public void keyReleased(KeyEvent e) {
328
    public void keyReleased(KeyEvent e) {
329
    }
329
    }
330
330
331
    public void keyTyped(KeyEvent e) {
331
    public void keyTyped(KeyEvent e) {
332
    }
332
    }
333
333
334
    public void focusGained(FocusEvent e) {
334
    public void focusGained(FocusEvent e) {
335
        repaint();
335
        repaint();
336
    }
336
    }
337
337
338
    public void focusLost(FocusEvent e) {
338
    public void focusLost(FocusEvent e) {
339
        repaint();
339
        repaint();
340
    }
340
    }
341
}
341
}
342
 
342