home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 November
/
Chip_1998-11_cd.bin
/
tema
/
Cafe
/
jfc.bin
/
BasicHSVChooserPanel.java
< prev
next >
Wrap
Text File
|
1998-02-26
|
19KB
|
685 lines
/*
* @(#)BasicHSVChooserPanel.java 1.5 98/02/02
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing.plaf.basic;
import com.sun.java.swing.*;
import com.sun.java.swing.event.*;
import com.sun.java.swing.plaf.ComponentUI;
import com.sun.java.swing.plaf.ColorChooserUI;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
/**
* The standard HSV chooser.
* <p>
* Warning: serialized objects of this class will not be compatible with
* future swing releases. The current serialization support is appropriate
* for short term storage or RMI between Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*
* @version 1.5 02/02/98
* @author James Gosling
* @author Amy Fowler
* @author Tom Santos
*/
public class BasicHSVChooserPanel extends ColorChooserPanel implements PropertyChangeListener, Serializable {
// Note: layout manager code was lifted directly from Jame's
// original color chooser; it really needs to be re-written
// to handle sizing better and to NOT rely on the order of
// children added in laying things out.
//
static int preferredWidth = 300;
static int preferredHeight = 200;
static Dimension preferredSize = new Dimension(preferredWidth, preferredHeight);
static int butGap = 2;
protected Spinner hue, saturation, brightness;
protected ColorPatch resultColor;
protected HueLightnessPatch hlp;
protected ColorWheel wheel;
Color color = Color.red;
public BasicHSVChooserPanel() {
super();
}
public BasicHSVChooserPanel( Color startColor ) {
color = startColor;
}
public int[] getHSBColor() {
Color color = getColor();
int[] result = new int[ 3 ];
float[] hsb = Color.RGBtoHSB( color.getRed(), color.getGreen(), color.getBlue(), null );
result[ 0 ] = (int)(hsb[ 0 ] * 100 + 0.5);
result[ 1 ] = (int)(hsb[ 1 ] * 100 + 0.5);
result[ 2 ] = (int)(hsb[ 2 ] * 100 + 0.5);
return result;
}
public Color getColor() {
return color;
}
public void setColor( Color newColor ) {
color = newColor;
// Set my variables
float[] hsbColor = Color.RGBtoHSB( color.getRed(), color.getGreen(), color.getBlue(), null );
int rgbColor = Color.HSBtoRGB( hsbColor[ 0 ], hsbColor[ 1 ], hsbColor[ 2 ] );
hlp.setColor( rgbColor );
setSpinners( hsbColor );
wheel.setTheta( hsbColor[ 0 ] * 360 + 0.5 );
resultColor.setColor( rgbColor );
}
/**
* The background color, foreground color, and font are already set to the
* defaults from the defaults table before this method is called.
*/
public void installChooserPanel() {
// Currently this UI implementation really hard-codes
// and depends-on all these subcomponents, therefore,
// for now, we won't break these out into overridable
// subcomponent creation methods.
setLayout(new ColorChooserLayout());
int[] hsb = getHSBColor();
// Create right-hand color patch to display current color
resultColor = new ColorPatch();
resultColor.setBorder(UIManager.getBorder("ColorChooser.selectedColorBorder"));
//resultColor.addPropertyChangeListener(this);
// Create spinners to display HSB
hue = new Spinner(hsb[ 0 ], "\u00B0 H");
hue.setMinimum(0);
hue.setMaximum(100);
saturation = new Spinner(hsb[ 1 ], "% S");
saturation.setMinimum(0);
saturation.setMaximum(100);
brightness = new Spinner(hsb[ 2 ], "% B");
brightness.setMinimum(0);
brightness.setMaximum(100);
// Create hue lightness patch (in center of color wheel)
hlp = new HueLightnessPatch(resultColor, hue, saturation, brightness);
// Note: Order of added children critical to layout manager!
add(hlp); // child0
saturation.addAdjustmentListener(hlp);
brightness.addAdjustmentListener(hlp);
// Create color wheel
wheel = new ColorWheel(hlp, hue);
hue.setWrap(true);
add(wheel); // child1
add(resultColor); //child2
add(hue); //child3
add(saturation); //child4
add(brightness); //child5
resultColor.addPropertyChangeListener( this );
}
public void uninstallChooserPanel() {
resultColor.removePropertyChangeListener( this );
setLayout(null);
remove(hlp);
remove(wheel);
remove(resultColor);
remove(hue);
remove(saturation);
remove(brightness);
hlp = null;
wheel = null;
resultColor = null;
hue = saturation = brightness = null;
}
public void propertyChange(PropertyChangeEvent e) {
if ( e.getSource() == resultColor && e.getPropertyName().equals( "color" ) ) {
Color newColor = (Color)e.getNewValue();
Color oldColor = getColor();
fireColorPropertyChange( oldColor, newColor );
}
}
protected void setSpinners(float hsb[]) {
float hueValue = hue.getValue();
float satValue = saturation.getValue();
float brightValue = brightness.getValue();
if (hueValue != hsb[0]) {
hue.setValue((int) (hsb[0] * 360 + 0.5));
}
if (satValue != hsb[1]) {
saturation.setValue((int) (hsb[1] * 100 + 0.5));
}
if (brightValue != hsb[2]) {
brightness.setValue((int) (hsb[2] * 100 + 0.5));
}
}
class ColorChooserLayout implements LayoutManager, Serializable {
public void addLayoutComponent(String name, Component comp) { }
public void removeLayoutComponent(Component comp) { }
public Dimension preferredLayoutSize(Container cont) {
return preferredSize;
}
public Dimension minimumLayoutSize(Container cont) {
return preferredLayoutSize(cont);
}
public void layoutContainer(Container cont) {
int ncomp = cont.getComponentCount();
int butWidth = 16;
Rectangle r = cont.getBounds();
Insets insets = cont.getInsets();
int h = r.height - insets.top - insets.bottom;
int w = r.width - insets.left - insets.right;
int xoffset = insets.left;
int yoffset = insets.top;
for (int i = 3; i < ncomp; i++) {
Dimension dim = cont.getComponent(i).getMinimumSize();
if (dim.width > butWidth)
butWidth = dim.width;
}
// compute diameter for color wheel
int diameter = h;
int r3 = w - butWidth - butGap;
if (r3 < diameter)
diameter = r3;
butWidth = w - diameter - butGap;
// inside saturation/lightness square
Component c = cont.getComponent(0);
r3 = (int) (diameter * (.75 * .71));
c.setBounds(xoffset + ((diameter - r3) >> 1), yoffset + ((diameter - r3) >> 1),
r3, r3);
// outside wheel
c = cont.getComponent(1);
c.setBounds(xoffset, yoffset + ((h - diameter) >> 1), diameter, diameter);
int y = 0;
for (int i = 3; i < ncomp; i++) {
c = cont.getComponent(i);
int dh = c.getMinimumSize().height;
c.setBounds(xoffset + w - butWidth, yoffset + y, butWidth, dh);
y += dh + butGap;
}
// colorPatch on the side
c = cont.getComponent(2);
c.setBounds(xoffset + w - butWidth, yoffset + y, butWidth, h - y);
}
}
}
class ImageComponent extends JComponent implements ImageObserver {
protected Image img;
private boolean imgKnown;
protected Dimension isize = new Dimension(-1, -1);
protected Dimension prefsize = new Dimension(0, 0);
boolean fixedSize = false;
long lastUpdateTime = 0;
public ImageComponent () {
super();
}
public ImageComponent (Image img) {
super();
setImage(img);
}
public ImageComponent (String name) {
super();
setImage(getToolkit().getImage(name));
}
public void setSize(int w, int h) {
if (w != isize.width || h != isize.height) {
isize.width = w;
isize.height = h;
invalidate();
}
}
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
setSize(width, height);
}
public void setImage(Image img) {
if (this.img == img)
return;
this.img = img;
if (img != null)
setSize(img.getWidth(this), img.getHeight(this));
if (isShowing())
repaint(10);
}
private synchronized void waitSize() {
if (img != null)
try {
while (isize.width < 0 || isize.height < 0)
wait();
} catch(InterruptedException i) {
}
}
protected boolean immediatePaint() {
return true;
}
public synchronized boolean imageUpdate(Image img,
int infoflags,
int x, int y,
int width, int height) {
long t = System.currentTimeMillis();
if ( /* lastUpdateTime+500<t || */ (infoflags & (ALLBITS | FRAMEBITS)) != 0) {
if (immediatePaint()) {
Graphics g = getGraphics();
if ( g != null ) {
paint(g);
g.dispose();
}
} else
repaint( /* 1 */ 0);
lastUpdateTime = t;
}
if ((infoflags & (ERROR | ABORT)) != 0) {
img = null;
isize.width = 0;
isize.height = 0;
notifyAll();
return false;
}
if ((infoflags & WIDTH) != 0)
isize.width = img.getWidth(this);
if ((infoflags & HEIGHT) != 0)
isize.height = img.getHeight(this);
notifyAll();
return (infoflags & ALLBITS) == 0;
}
public Dimension getPreferredSize() {
Insets insets = getInsets();
waitSize();
prefsize.width = isize.width + insets.left + insets.right;
prefsize.height = isize.height + insets.top + insets.bottom;
return prefsize;
}
public Dimension getMinimumSize() {
return getPreferredSize();
}
protected void locateImage() {
};
public void paint(Graphics g) {
Insets insets = getInsets();
Image i = img;
if (i == null) {
locateImage();
if ((i = img) == null)
return;
}
if ( g == null ) System.out.println( "NULL GRAPHICS" );
if ( insets == null ) System.out.println( "NULL INSETS" );
g.drawImage(i, insets.left, insets.top, this);
}
public void update(Graphics g) {
paint(g);
}
}
class ColorWheel extends ImageComponent implements AdjustmentListener {
private static Image img;
SyntheticImage vSrc;
int sx, sy;
private static int cursorWidth = 3;
HueLightnessPatch hlp;
Adjustable hue;
ColorWheel (HueLightnessPatch hlp, Adjustable hue) {
super();
this.hlp = hlp;
this.hue = hue;
hue.setMinimum(0);
hue.setMaximum(359);
hue.addAdjustmentListener(this);
enableEvents(AWTEvent.MOUSE_EVENT_MASK
| AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
protected void processMouseEvent(MouseEvent e) {
switch (e.getID()) {
case MouseEvent.MOUSE_RELEASED:
// moveSel(e.getX(), e.getY());
// if (continuous) notfyListener();
// break;
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_DRAGGED:
moveSel(e.getX(), e.getY());
}
}
protected void processMouseMotionEvent(MouseEvent e) {
processMouseEvent(e);
}
public void setTheta( double newTheta ) {
lastCursorAngle = (int)newTheta;
repaint();
}
protected void locateImage() {
if (img == null) {
final Dimension s = getSize();
vSrc = new SyntheticImage() {
{
this.width = s.width;
this.height = s.height;
}
protected void computeRow(int y, int[] row) {
int r = width >> 1;
int r2 = r * 3 / 4;
int dy = y - r;
for (int x = width; --x >= 0;) {
int dx = x - r;
int dr = (int) (Math.sqrt(dy * dy + dx * dx + dx + dy + 0.5) + 0.5);
if (dr >= r || dr <= r2)
row[x] = 0;
else {
float brightness = 1.0f;
float saturation = 1.0f;
int theta = (int) (Math.atan2(dx, dy) * (180 / Math.PI));
if (theta < 0)
theta += 360;
if (dr >= r - 2 || dr <= r2 + 2) {
int lt = theta + (360 - 45);
if (lt >= 360)
lt -= 360;
if (lt >= 180)
lt = 360 - lt;
lt = lt - 90;
if (dr <= r2 + 2)
lt = -lt;
if (lt < 0)
brightness = 1.0f - lt / (float) (-180);
else
saturation = 1.0f - lt / (float) 120;
}
row[x] = Color.HSBtoRGB(theta / ((float) 360.0),
saturation, brightness);
}
}
}
};
setImage(getToolkit().createImage(vSrc));
}
}
int lastCursorAngle = -1;
public void adjustmentValueChanged(AdjustmentEvent e) {
int theta = e.getValue();
hlp.setColor(Color.HSBtoRGB(theta / ((float) 360.0), 1, 1));
hlp.propogateColor();
Graphics g = getGraphics();
if (g != null) {
paintCursor(g, lastCursorAngle);
paintCursor(g, lastCursorAngle = theta);
g.dispose();
}
}
private void moveSel(int tx, int ty) {
if (tx == sx && ty == sy)
return;
sx = tx;
sy = ty;
int dx = sx - (isize.width >> 1);
int dy = sy - (isize.height >> 1);
int theta = (int) (Math.atan2(dx, dy) * (180 / Math.PI));
if (theta < 0)
theta += 360;
hue.setValue(theta);
}
public void paint(Graphics g) {
super.paint(g);
paintCursor(g, lastCursorAngle);
}
private void paintCursor(Graphics g, int theta) {
if (theta < 0)
return;
g.setColor(Color.white);
g.setXORMode(Color.black);
int xc = isize.width >> 1; // Center
int yc = isize.height >> 1;
int xr = (int) (Math.sin(theta * (Math.PI / 180)) * xc); // Radius vector
int yr = (int) (Math.cos(theta * (Math.PI / 180)) * yc);
g.drawArc(xc + xr - (xr >> 3) - (xc >> 4),
yc + yr - (yr >> 3) - (yc >> 4),
xc >> 3, xc >> 3, 0, 360);
}
public void update(Graphics g) {
paint(g);
}
}
class HueLightnessPatch extends ImageComponent implements AdjustmentListener {
int sx, sy;
private static int cursorWidth = 3;
SyntheticImage hli;
ColorPatch target;
Adjustable hue;
Adjustable saturation;
Adjustable brightness;
int color;
HueLightnessPatch(ColorPatch target,
Adjustable hue, Adjustable saturation, Adjustable brightness) {
super();
this.target = target;
this.hue = hue;
this.saturation = saturation;
this.brightness = brightness;
target.setColor(0xFF0000);
enableEvents(AWTEvent.MOUSE_EVENT_MASK
| AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
protected void locateImage() {
if (img == null) {
final Dimension s = getSize();
final int c0 = color;
final Adjustable imageHue = hue;
hli = new SyntheticImage() {
int color, nextColor;
Adjustable hue;
boolean changed;
{
this.hue = imageHue;
this.width = s.width;
this.height = s.height;
nextFrame(c0);
}
public synchronized void nextFrame(int c) {
c |= pixMask << 24;
if (color != c) {
changed = true;
notifyAll();
}
nextColor = c;
}
private synchronized void waitNextColor() {
try {
while (!changed)
wait();
}
catch(InterruptedException e) {
}
changed = false;
color = nextColor;
}
protected boolean isStatic() {
return false;
}
protected void computeRow(int y, int[] row) {
if (y == 0)
waitNextColor();
float theta = hue.getValue() / ((float) 360.0);
float brightness = (height - y - 1) / (float) (height - 1);
int w = width;
for (int i = w; --i >= 0;) {
float sat = (w - i - 1) / (float) (w - 1);
row[i] = Color.HSBtoRGB(theta, sat, brightness);
}
}
};
setImage(getToolkit().createImage(hli));
}
}
protected void processMouseEvent(MouseEvent e) {
switch (e.getID()) {
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
case MouseEvent.MOUSE_DRAGGED:
int h = isize.height;
int w = isize.width;
brightness.setValue((h - e.getY() - 1) * 100 / (h - 1));
saturation.setValue((w - e.getX() - 1) * 100 / (w - 1));
}
}
public void setColor(int c) {
color = c;
if (hli != null)
hli.nextFrame(c);
}
protected void processMouseMotionEvent(MouseEvent e) {
processMouseEvent(e);
}
public void adjustmentValueChanged(AdjustmentEvent e) {
int h = isize.height - 1;
int w = isize.width - 1;
int tx = w - saturation.getValue() * w / 100;
int ty = h - brightness.getValue() * h / 100;
Graphics g = getGraphics();
if (g != null) {
paintCursor(g, sx, sy);
paintCursor(g, tx, ty);
g.dispose();
}
sx = tx;
sy = ty;
propogateColor();
}
void propogateColor() {
int h = isize.height;
int w = isize.width;
target.setColor(Color.HSBtoRGB(hue.getValue() / ((float) 360.0),
saturation.getValue() / ((float) 100.0),
brightness.getValue() / ((float) 100.0)));
}
public void paint(Graphics g) {
super.paint(g);
paintCursor(g, sx, sy);
}
private void paintCursor(Graphics g, int sx, int sy) {
g.setColor(Color.white);
g.setXORMode(Color.black);
g.drawLine(sx - 3, sy, sx + 3, sy);
g.drawLine(sx, sy - 3, sx, sy + 3);
}
public void update(Graphics g) {
paint(g);
}
}
class ColorPatch extends ImageComponent {
SyntheticImage vSrc;
int patchColor;
protected void locateImage() {
if (img == null) {
final Dimension s = getSize();
final int c0 = patchColor;
vSrc = new SyntheticImage() {
int color, nextColor;
boolean changed;
{
this.width = s.width;
this.height = s.height;
nextFrame(c0);
}
public synchronized void nextFrame(int c) {
c |= pixMask << 24;
if (color != c) {
changed = true;
notifyAll();
}
nextColor = c;
}
private synchronized void waitNextColor() {
try {
while (!changed)
wait();
}
catch(InterruptedException e) {
}
changed = false;
color = nextColor;
}
protected boolean isStatic() {
return false;
}
protected void computeRow(int y, int[] row) {
if (y == 0)
waitNextColor();
int C = color;
for (int i = row.length; --i >= 0;)
row[i] = C;
}
};
setImage(getToolkit().createImage(vSrc));
}
}
public void setColor(int c) {
int old = patchColor;
patchColor = c;
if (vSrc != null)
vSrc.nextFrame(c);
if (old != c) {
firePropertyChange( "color", new Color( old ), new Color( patchColor ) );
}
}
}