/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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.util.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.text.*;
import de.muntjak.tinylookandfeel.controlpanel.*;
/**
* SBChooser
*
* @version 1.0
* @author Hans Bickel
*/
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);
}
}
}