/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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); } } }