|
From: <dqu...@us...> - 2003-08-11 10:25:05
|
Update of /cvsroot/jsynthlib/JSynthLib/com/dreamfabric
In directory sc8-pr-cvs1:/tmp/cvs-serv29356
Added Files:
DKnob.java
Log Message:
knob widget from ko...@dr..., I made some changes and optimizations.
--- NEW FILE: DKnob.java ---
/*
* DKnob.java
* (c) 2000 by Joakim Eriksson
*
* DKnob is a component similar to JSlider but with
* round "user interface", a knob.
*/
package com.dreamfabric;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.*;
/**
@author Denis Queffeulou for some modifications and optimization.
*/
public class DKnob extends JComponent
{
private final static float START = 225;
private final static float LENGTH = 270;
private final static float START_ANG = (START/360)*(float)Math.PI*2;
private final static float LENGTH_ANG = (LENGTH/360)*(float)Math.PI*2;
private final static float LENGTH_ANG_DIV10 = (float)(LENGTH_ANG/10.01);
private final static float DRAG_RES = (float) 0.01;
private final static float MULTIP = 180 / (float)Math.PI;
private final static Color DEFAULT_FOCUS_COLOR = new Color(0x8080ff);
private int SHADOWX = 1;
private int SHADOWY = 1;
private float DRAG_SPEED;
private float CLICK_SPEED;
private int size;
private int middle;
public final static int SIMPLE = 1;
public final static int ROUND = 2;
public final static int SIMPLE_MOUSE_DIRECTION = 3;
private int dragType = ROUND;
public final static int DEFAULT_WIDTH = 60;
public final static int DEFAULT_HEIGHT = 45;
private final static Dimension MIN_SIZE = new Dimension(40, 40);
private final static Dimension PREF_SIZE = new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
private final static float MID_OFFSET = (float)1./220;
// Set the antialiasing to get the right look!
private final static RenderingHints AALIAS =
new RenderingHints(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
private ChangeEvent changeEvent = null;
private EventListenerList listenerList = new EventListenerList();
private Arc2D hitArc = new Arc2D.Float(Arc2D.PIE);
private float ang = (float) START_ANG;
private float val;
private int dragpos = -1;
private float startVal;
private Color focusColor;
private double lastAng;
private int mWidth;
private int mHeight;
/** value displayed if not null */
private String mValueAsString;
/**
Knob with default size.
*/
public DKnob() {
this(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
public DKnob(int aWidth, int aHeight) {
mWidth = aWidth;
mHeight = aHeight;
DRAG_SPEED = 0.0075F;//0.01F;
CLICK_SPEED = 0.01F;
SHADOWX = 1;
SHADOWY = 1;
focusColor = DEFAULT_FOCUS_COLOR;
setPreferredSize(PREF_SIZE);
hitArc.setAngleStart(235); // Degrees ??? Radians???
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
dragpos = me.getX() + me.getY();
startVal = val;
// Fix last angle
int xpos = middle - me.getX();
int ypos = middle - me.getY();
lastAng = Math.atan2(xpos, ypos);
requestFocus();
}
public void mouseClicked(MouseEvent me) {
hitArc.setAngleExtent(-(LENGTH + 20));
if (hitArc.contains(me.getX(), me.getY())) {
hitArc.setAngleExtent(MULTIP * (ang-START_ANG)-10);
if (hitArc.contains(me.getX(), me.getY())) {
decValue();
} else incValue();
}
}
});
// Let the user control the knob with the mouse
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent me) {
if ( dragType == SIMPLE) {
float f = DRAG_SPEED * (float)((me.getX() + me.getY()) - dragpos);
setValue(startVal + f);
}
else if (dragType == SIMPLE_MOUSE_DIRECTION) {
float f = (float)(DRAG_SPEED * (me.getX() + me.getY() - dragpos));
setValue(startVal - f);
}
else if ( dragType == ROUND) {
// Measure relative the middle of the button!
int xpos = middle - me.getX();
int ypos = middle - me.getY();
double ang = Math.atan2(xpos, ypos);
double diff = lastAng - ang;
setValue((float) (getValue() + (diff / LENGTH_ANG)));
lastAng = ang;
}
}
public void mouseMoved(MouseEvent me) {
}
});
// Let the user control the knob with the keyboard
addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public void keyPressed(KeyEvent e) {
int k = e.getKeyCode();
if (k == e.VK_RIGHT)
incValue();
else if (k == e.VK_LEFT)
decValue();
}
});
// Handle focus so that the knob gets the correct focus highlighting.
addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
repaint();
}
public void focusLost(FocusEvent e) {
mValueAsString = null;
repaint();
}
});
}
public void setDragType(int type) {
dragType = type;
}
public int getDragType() {
return dragType;
}
public boolean isManagingFocus() {
return true;
}
public boolean isFocusTraversable() {
return true;
}
private void incValue() {
setValue(val + CLICK_SPEED);
}
private void decValue() {
setValue(val - CLICK_SPEED);
}
public float getValue() {
return val;
}
public void setValue(float val) {
if (val < 0) val = 0;
if (val > 1) val = 1;
this.val = val;
ang = START_ANG - (float) LENGTH_ANG * val;
repaint();
fireChangeEvent();
}
/**
Set the value as string (for display if not null)
*/
public void setValueAsString(String aStrValue) {
mValueAsString = aStrValue;
}
public void addChangeListener(ChangeListener cl) {
listenerList.add(ChangeListener.class, cl);
}
public void removeChangeListener(ChangeListener cl) {
listenerList.remove(ChangeListener.class, cl);
}
public Dimension getMinimumSize() {
return MIN_SIZE;
}
protected void fireChangeEvent() {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == ChangeListener.class) {
// Lazily create the event:
if (changeEvent == null)
changeEvent = new ChangeEvent(this);
((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
}
}
}
/**
Paint the DKnob
*/
public void paint(Graphics g) {
// denis: i set the size because I can't deal with layout and resize consequences
int width = mWidth;//getWidth();
int height = mHeight;//getHeight();
// size = Math.min(width, height) - 22;
// le dessin est plus large que haut
size = width - 22;
int oSizeDiv2 = size/2;
int oOffset = 5;//10
middle = oOffset + oSizeDiv2;
if (g instanceof Graphics2D) {
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(getParent().getBackground());
g2d.addRenderingHints(AALIAS);
// For the size of the "mouse click" area
hitArc.setFrame(4, 4, size+12, size+12);
}
// Paint the "markers"
for (float a2 = START_ANG; a2 >= START_ANG - LENGTH_ANG; a2 = a2 - LENGTH_ANG_DIV10)
{
int x = oOffset + oSizeDiv2 + (int)((6+oSizeDiv2) * Math.cos(a2));
int y = oOffset + oSizeDiv2 - (int)((6+oSizeDiv2) * Math.sin(a2));
g.drawLine(oOffset + oSizeDiv2, oOffset + oSizeDiv2, x, y);
}
// Paint focus if in focus
if (hasFocus()) {
g.setColor(focusColor);
} else {
g.setColor(Color.white);
}
g.fillOval(oOffset, oOffset, size, size);
g.setColor(Color.gray);
g.fillOval(oOffset + 4 + SHADOWX, oOffset + 4 + SHADOWY, size-8, size-8);
g.setColor(Color.black);
g.drawArc(oOffset, oOffset, size, size, 315, 270);
g.fillOval(oOffset + 4, oOffset + 4, size-8, size-8);
g.setColor(Color.white);
double oCos = Math.cos(ang);
double oSin = Math.sin(ang);
int x = oOffset + oSizeDiv2 + (int)(oSizeDiv2 * oCos);
int y = oOffset + oSizeDiv2 - (int)(oSizeDiv2 * oSin);
g.drawLine(oOffset + oSizeDiv2, oOffset + oSizeDiv2, x, y);
g.setColor(Color.gray);
int s2 = (int) Math.max(size / 6, 6);
g.drawOval(oOffset + s2, oOffset + s2, size - s2*2, size - s2*2);
int dx = (int)(2 * oSin);
int dy = (int)(2 * oCos);
/*
g.drawLine(oOffset + dx + oSizeDiv2, oOffset + dy + oSizeDiv2, x, y);
g.drawLine(oOffset - dx + oSizeDiv2, oOffset - dy + oSizeDiv2, x, y);
*/
// denis: i prefer rectangular look for indicator needle
int xPoints[] = new int[] {oOffset + dx + oSizeDiv2, x + dx, x - dx, oOffset - dx + oSizeDiv2};
int yPoints[] = new int[] {oOffset + dy + oSizeDiv2, y + dy, y - dy, oOffset - dy + oSizeDiv2};
// denis: hightlight the middle for symetric knobs
if (val > (0.5 - MID_OFFSET) && val < (0.5 + MID_OFFSET))
g.setColor(Color.white);
else
g.setColor(Color.lightGray);
g.fillPolygon(xPoints, yPoints, 4);
// denis: display value
if (mValueAsString != null) {
g.setColor(Color.white);
g.drawString(mValueAsString, oSizeDiv2-5, height-10);
}
}
}
|