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