Subversion Repositories svn.mios

Rev

Rev 213 | Rev 657 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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