/*******************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tiny Look and Feel * * (C) Copyright 2003 - 2007 Hans Bickel * * For
* licensing information and credits, please refer to the * comment in file
* de.muntjak.tinylookandfeel.TinyLookAndFeel * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
package de.muntjak.tinylookandfeel.controlpanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.border.EtchedBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
/**
* SBChooser
*
* @version 1.0
* @author Hans Bickel
*/
@SuppressWarnings (
{ "all" } )
public class SBChooser extends JDialog
{
private static SBChooser myInstance;
private static int sat, bri;
private Color reference, outColor;
private JSlider satSlider, briSlider;
private JTextField satField, briField;
private JTextField redField, greenField, blueField;
private TwoColorField twoColorField;
private ColorField referenceField;
private boolean keyInput = false;
private boolean valueIsAdjusting = false;
public SBChooser ( Frame frame )
{
super ( frame, "Saturation/Lightness", true );
setDefaultCloseOperation ( JDialog.HIDE_ON_CLOSE );
setupUI ( frame );
}
private void setupUI ( Frame frame )
{
ChangeListener sliderAction = new SliderAction ();
JPanel p1 = new JPanel ( new BorderLayout ( 12, 0 ) );
JPanel p2 = new JPanel ( new GridLayout ( 2, 1, 0, 8 ) );
JPanel p3 = new JPanel ( new FlowLayout ( FlowLayout.LEFT, 2, 4 ) );
JPanel p4 = new JPanel ( new BorderLayout ( 4, 0 ) );
// sliders
JPanel p5 = new JPanel ( new FlowLayout ( FlowLayout.LEFT, 0, 0 ) );
p4.add ( new JLabel ( "Saturation" ), BorderLayout.NORTH );
satSlider = new JSlider ( -100, 100, sat );
satSlider.addChangeListener ( sliderAction );
satSlider.setMajorTickSpacing ( 100 );
satSlider.setPaintTicks ( true );
p4.add ( satSlider, BorderLayout.CENTER );
satField = new JTextField ( "" + satSlider.getValue (), 4 );
satField.getDocument ().addDocumentListener ( new SatInputListener () );
satField.addKeyListener ( new ArrowKeyAction ( satField, -100, 100 ) );
satField.setHorizontalAlignment ( JTextField.CENTER );
p5.add ( satField );
p4.add ( p5, BorderLayout.EAST );
p2.add ( p4 );
p5 = new JPanel ( new FlowLayout ( FlowLayout.LEFT, 0, 0 ) );
p4 = new JPanel ( new BorderLayout ( 4, 0 ) );
p4.add ( new JLabel ( "Lightness" ), BorderLayout.NORTH );
briSlider = new JSlider ( -100, 100, bri );
briSlider.addChangeListener ( sliderAction );
briSlider.setMajorTickSpacing ( 100 );
briSlider.setPaintTicks ( true );
p4.add ( briSlider, BorderLayout.CENTER );
briField = new JTextField ( "" + briSlider.getValue (), 4 );
briField.getDocument ().addDocumentListener ( new BriInputListener () );
briField.addKeyListener ( new ArrowKeyAction ( briField, -100, 100 ) );
briField.setHorizontalAlignment ( JTextField.CENTER );
p5.add ( briField );
p4.add ( p5, BorderLayout.EAST );
p2.add ( p4 );
p3.add ( p2 );
p1.add ( p3, BorderLayout.CENTER );
// color panel
p2 = new JPanel ( new BorderLayout ( 0, 6 ) );
p3 = new JPanel ( new FlowLayout ( FlowLayout.LEFT, 4, 4 ) );
twoColorField = new TwoColorField ( reference );
p2.add ( twoColorField, BorderLayout.NORTH );
referenceField = new ColorField ( reference );
p2.add ( referenceField, BorderLayout.CENTER );
p3.add ( p2 );
p1.add ( p3, BorderLayout.EAST );
// RGB fields
p3 = new JPanel ( new FlowLayout ( FlowLayout.LEFT, 3, 8 ) );
p3.add ( new JLabel ( "R:" ) );
redField = new JTextField ( 4 );
redField.setHorizontalAlignment ( JTextField.CENTER );
redField.setEditable ( false );
p3.add ( redField );
p3.add ( new JLabel ( " G:" ) );
greenField = new JTextField ( 4 );
greenField.setHorizontalAlignment ( JTextField.CENTER );
greenField.setEditable ( false );
p3.add ( greenField );
p3.add ( new JLabel ( " B:" ) );
blueField = new JTextField ( 4 );
blueField.setHorizontalAlignment ( JTextField.CENTER );
blueField.setEditable ( false );
p3.add ( blueField );
p1.add ( p3, BorderLayout.SOUTH );
getContentPane ().add ( p1, BorderLayout.CENTER );
// buttons
p3 = new JPanel ( new FlowLayout ( FlowLayout.RIGHT, 12, 4 ) );
p3.setBorder ( new EtchedBorder () );
JButton b = new JButton ( "Cancel" );
b.addActionListener ( new CancelAction () );
p3.add ( b );
b = new JButton ( "OK" );
getRootPane ().setDefaultButton ( b );
b.addActionListener ( new OKAction () );
p3.add ( b );
getContentPane ().add ( p3, BorderLayout.SOUTH );
pack ();
Dimension size = getSize ();
setLocation ( frame.getLocationOnScreen ().x
+ ( frame.getWidth () - getSize ().width ) / 2, frame
.getLocationOnScreen ().y
+ ( frame.getHeight () - getSize ().height ) / 2 );
}
public static Color showSBChooser ( Frame frame, Color ref, Color inColor,
int s, int b )
{
if ( myInstance == null )
{
myInstance = new SBChooser ( frame );
}
myInstance.setColor ( ref, inColor, s, b );
myInstance.setVisible ( true );
return myInstance.outColor;
}
public static Color showSBChooser ( Frame frame, ControlPanel.SBField hsb )
{
if ( myInstance == null )
{
myInstance = new SBChooser ( frame );
}
myInstance.setColor ( hsb );
myInstance.setVisible ( true );
return myInstance.outColor;
}
public static void deleteInstance ()
{
myInstance = null;
}
public void setColor ( ControlPanel.SBField hsb )
{
reference = hsb.getColorReference ().getReferenceColor ();
outColor = hsb.getBackground ();
sat = hsb.getColorReference ().getSaturation ();
bri = hsb.getColorReference ().getBrightness ();
valueIsAdjusting = true;
satSlider.setValue ( sat );
briSlider.setValue ( bri );
valueIsAdjusting = false;
referenceField.setBackground ( reference );
twoColorField.setLowerColor ( outColor );
adjustColor ();
}
public void setColor ( Color ref, Color inColor, int s, int b )
{
reference = ref;
outColor = inColor;
sat = s;
bri = b;
valueIsAdjusting = true;
satSlider.setValue ( sat );
briSlider.setValue ( bri );
valueIsAdjusting = false;
referenceField.setBackground ( reference );
twoColorField.setLowerColor ( inColor );
adjustColor ();
}
private void showColor ( int s, int b )
{
sat = s;
bri = b;
adjustColor ();
}
private void adjustColor ()
{
outColor = getAdjustedColor ( reference, sat, bri );
twoColorField.setUpperColor ( outColor );
}
public static Color getAdjustedColor ( Color inColor, int sat, int bri )
{
Color briColor = inColor;
// first do brightening
if ( bri < 0 )
{
briColor = ColorRoutines.darken ( inColor, -bri );
}
else if ( bri > 0 )
{
briColor = ColorRoutines.lighten ( inColor, bri );
}
// then do saturation
Color satColor = ColorRoutines.getMaxSaturation ( briColor, ColorRoutines
.getHue ( inColor ) );
int r, g, b;
if ( sat >= 0 )
{
int dr = briColor.getRed () - satColor.getRed ();
int dg = briColor.getGreen () - satColor.getGreen ();
int db = briColor.getBlue () - satColor.getBlue ();
r = briColor.getRed () - ( int ) Math.round ( dr * sat / 100.0 );
g = briColor.getGreen () - ( int ) Math.round ( dg * sat / 100.0 );
b = briColor.getBlue () - ( int ) Math.round ( db * sat / 100.0 );
}
else
{
float d = ColorRoutines.getGreyValue ( briColor );
float dr = briColor.getRed () - d;
float dg = briColor.getGreen () - d;
float db = briColor.getBlue () - d;
r = ( int ) Math.round ( briColor.getRed () + dr * sat / 100.0 );
g = ( int ) Math.round ( briColor.getGreen () + dg * sat / 100.0 );
b = ( int ) Math.round ( briColor.getBlue () + db * sat / 100.0 );
}
return new Color ( r, g, b );
}
public static int getSat ()
{
return sat;
}
public static int getBri ()
{
return bri;
}
class TwoColorField extends JPanel
{
private Dimension size = new Dimension ( 60, 68 );
private Color upperColor, lowerColor;
TwoColorField ( Color c )
{
setBorder ( new LineBorder ( Color.BLACK, 1 ) );
upperColor = outColor;
lowerColor = c;
}
public Dimension getPreferredSize ()
{
return size;
}
void setUpperColor ( Color c )
{
upperColor = c;
redField.setText ( "" + c.getRed () );
greenField.setText ( "" + c.getGreen () );
blueField.setText ( "" + c.getBlue () );
repaint ( 0 );
}
void setLowerColor ( Color c )
{
lowerColor = c;
repaint ( 0 );
}
public void paint ( Graphics g )
{
super.paintBorder ( g );
g.setColor ( upperColor );
g.fillRect ( 1, 1, 58, 33 );
g.setColor ( lowerColor );
g.fillRect ( 1, 34, 58, 33 );
}
}
class ColorField extends JPanel
{
private Dimension size = new Dimension ( 60, 38 );
ColorField ( Color c )
{
setBorder ( new LineBorder ( Color.GRAY, 1 ) );
setBackground ( c );
}
public Dimension getPreferredSize ()
{
return size;
}
}
class SliderAction implements ChangeListener
{
public void stateChanged ( ChangeEvent e )
{
if ( !keyInput )
{
if ( e.getSource ().equals ( satSlider ) )
{
satField.setText ( "" + satSlider.getValue () );
}
else
{
briField.setText ( "" + briSlider.getValue () );
}
}
if ( valueIsAdjusting )
return;
showColor ( satSlider.getValue (), briSlider.getValue () );
}
}
class SatInputListener implements DocumentListener
{
public void changedUpdate ( DocumentEvent e )
{
}
public void insertUpdate ( DocumentEvent e )
{
update ( e );
}
public void removeUpdate ( DocumentEvent e )
{
update ( e );
}
private void update ( DocumentEvent e )
{
Document doc = e.getDocument ();
try
{
String text = doc.getText ( 0, doc.getLength () );
try
{
int val = Integer.parseInt ( text );
keyInput = true;
satSlider.setValue ( val );
keyInput = false;
}
catch ( NumberFormatException ignore )
{
}
}
catch ( BadLocationException ignore )
{
}
}
}
class BriInputListener implements DocumentListener
{
public void changedUpdate ( DocumentEvent e )
{
}
public void insertUpdate ( DocumentEvent e )
{
update ( e );
}
public void removeUpdate ( DocumentEvent e )
{
update ( e );
}
private void update ( DocumentEvent e )
{
Document doc = e.getDocument ();
try
{
String text = doc.getText ( 0, doc.getLength () );
try
{
int val = Integer.parseInt ( text );
keyInput = true;
briSlider.setValue ( val );
keyInput = false;
}
catch ( NumberFormatException ignore )
{
}
}
catch ( BadLocationException ignore )
{
}
}
}
class ArrowKeyAction extends KeyAdapter implements ActionListener
{
private JTextField theField;
private javax.swing.Timer keyTimer;
private int step, min, max;
ArrowKeyAction ( JTextField field, int min, int max )
{
theField = field;
this.min = min;
this.max = max;
keyTimer = new javax.swing.Timer ( 20, this );
}
public void keyPressed ( KeyEvent e )
{
if ( e.getKeyCode () == 38 )
{ // up => decrease
step = 1;
if ( e.getModifiers () == KeyEvent.SHIFT_MASK )
{
step = 10;
}
changeVal ();
keyTimer.setInitialDelay ( 300 );
keyTimer.start ();
}
else if ( e.getKeyCode () == 40 )
{ // up => increase
step = -1;
if ( e.getModifiers () == KeyEvent.SHIFT_MASK )
{
step = -10;
}
changeVal ();
keyTimer.setInitialDelay ( 300 );
keyTimer.start ();
}
}
public void keyReleased ( KeyEvent e )
{
keyTimer.stop ();
}
public void actionPerformed ( ActionEvent e )
{
changeVal ();
}
private void changeVal ()
{
int val = Integer.parseInt ( theField.getText () ) + step;
if ( val > max )
val = max;
else if ( val < min )
val = min;
theField.setText ( "" + val );
}
}
class OKAction implements ActionListener
{
public void actionPerformed ( ActionEvent e )
{
setVisible ( false );
}
}
class CancelAction implements ActionListener
{
public void actionPerformed ( ActionEvent e )
{
outColor = null;
setVisible ( false );
}
}
}