colorpicker-1.0.0/0000755000175000017500000000000011452722626013355 5ustar andrewandrewcolorpicker-1.0.0/License.html0000644000175000017500000000405611437472304015630 0ustar andrewandrew Source code, binaries and/or any other resources in the package labeled "com.bric" are copyright (c) 2010 by Jeremy Wood. They are available under the Modified BSD license (see below).

Any resources not in the "com.bric" package may be subject to additional license terms and restrictions.

If you have any questions about this jar, the relevant licenses, the source code, etc., please contact mickleness+java@gmail.com.

This jar is part of the "javagraphics" project, discussed here

Modified BSD License

Copyright (c) 2010, Jeremy Wood.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* The name of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. colorpicker-1.0.0/META-INF/0000755000175000017500000000000011452722626014515 5ustar andrewandrewcolorpicker-1.0.0/META-INF/MANIFEST.MF0000644000175000017500000000011711437472304016144 0ustar andrewandrewManifest-Version: 1.0 Sealed: false Main-Class: com/bric/swing/ColorPickerDemo colorpicker-1.0.0/com/0000755000175000017500000000000011452722626014133 5ustar andrewandrewcolorpicker-1.0.0/com/bric/0000755000175000017500000000000011452722626015052 5ustar andrewandrewcolorpicker-1.0.0/com/bric/swing/0000755000175000017500000000000011452722626016201 5ustar andrewandrewcolorpicker-1.0.0/com/bric/swing/ImageTransferable.java0000644000175000017500000000253411437472304022421 0ustar andrewandrew/* * @(#)ImageTransferable.java * * $Date: 2009-02-20 01:34:41 -0600 (Fri, 20 Feb 2009) $ * * Copyright (c) 2009 by Jeremy Wood. * All rights reserved. * * The copyright of this software is owned by Jeremy Wood. * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * Jeremy Wood. For details see accompanying license terms. * * This software is probably, but not necessarily, discussed here: * http://javagraphics.blogspot.com/ * * And the latest version should be available here: * https://javagraphics.dev.java.net/ */ package com.bric.swing; import java.awt.Image; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; class ImageTransferable implements Transferable { Image img; public ImageTransferable(Image i) { img = i; } public Object getTransferData(DataFlavor f) throws UnsupportedFlavorException, IOException { if(f.equals(DataFlavor.imageFlavor)==false) throw new UnsupportedFlavorException(f); return img; } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[] {DataFlavor.imageFlavor}; } public boolean isDataFlavorSupported(DataFlavor flavor) { return(flavor.equals(DataFlavor.imageFlavor)); } } colorpicker-1.0.0/com/bric/swing/resources/0000755000175000017500000000000011452722626020213 5ustar andrewandrewcolorpicker-1.0.0/com/bric/swing/resources/DialogFooter_sp.properties0000644000175000017500000000005511437472304025407 0ustar andrewandrewdialogCancelButton=Cancelar dialogOKButton=OKcolorpicker-1.0.0/com/bric/swing/resources/DialogFooter_de.properties0000644000175000017500000000005611437472304025356 0ustar andrewandrewdialogCancelButton=Abbrechen dialogOKButton=OKcolorpicker-1.0.0/com/bric/swing/resources/DialogFooter_nl.properties0000644000175000017500000000005711437472304025400 0ustar andrewandrewdialogCancelButton=Annuleeren dialogOKButton=OKcolorpicker-1.0.0/com/bric/swing/resources/ColorPicker.properties0000644000175000017500000000103011437472304024535 0ustar andrewandrew# # Copyright (c) 2008 Jeremy Wood # E-mail: mickleness@gmail.com # All rights reserved. # # The copyright of this software is owned by Jeremy Wood. # You may not use, copy or modify this software, except in # accordance with the license agreement you entered into with # Jeremy Wood. For details see accompanying license terms. # ColorPickerDialogTitle=Choose a Color Copy=Copy blueLabel=Blue: greenLabel=Green: redLabel=Red: brightnessLabel=Bri: hueLabel=Hue: saturationLabel=Sat: hexLabel=Hex: opacityLabel=Opacity: alphaLabel=Alpha:colorpicker-1.0.0/com/bric/swing/resources/ColorPicker_ru.properties0000644000175000017500000000203211437472304025246 0ustar andrewandrew# # Copyright (c) 2008 Jeremy Wood # E-mail: mickleness@gmail.com # All rights reserved. # # The copyright of this software is owned by Jeremy Wood. # You may not use, copy or modify this software, except in # accordance with the license agreement you entered into with # Jeremy Wood. For details see accompanying license terms. # ColorPickerDialogTitle=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0446\u0432\u0435\u0442 Copy=\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c Cancel=\u041e\u0442\u043c\u0435\u043d\u0430 OK=OK blueLabel=\u0421\u0438\u043d\u0438\u0439: greenLabel=\u0417\u0435\u043b\u0451\u043d\u044b\u0439: redLabel=\u041a\u0440\u0430\u0441\u043d\u044b\u0439: brightnessLabel=\u042f\u0440\u043a\u043e\u0441\u0442\u044c: hueLabel=\u0422\u043e\u043d: saturationLabel=\u041d\u0430\u0441\u044b\u0449\u0435\u043d\u043d\u043e\u0441\u0442\u044c: hexLabel=Hex: opacityLabel=\u041d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u044c: alphaLabel=\u0410\u043b\u044c\u0444\u0430:colorpicker-1.0.0/com/bric/swing/resources/DialogFooter_es.properties0000644000175000017500000000012211437472304025367 0ustar andrewandrewdialogCancelButton=Cancelar dialogOKButton=OK dialogYesButton=Sí dialogNoButton=Nocolorpicker-1.0.0/com/bric/swing/resources/ColorPicker_sp.properties0000644000175000017500000000124511437472304025247 0ustar andrewandrew# # Copyright (c) 2008 Jeremy Wood # E-mail: mickleness@gmail.com # All rights reserved. # # The copyright of this software is owned by Jeremy Wood. # You may not use, copy or modify this software, except in # accordance with the license agreement you entered into with # Jeremy Wood. For details see accompanying license terms. # ColorPickerDialogTitle=Elija un color Copy=Copiar blueLabel=Azul: greenLabel=Verde: redLabel=Rojo: brightnessLabel=Luminosidad: # not sure, could be 'brillo' hueLabel=Hue: # dont know : matiz ? 'Tinte' is more the tint saturationLabel=Saturación: hexLabel=Hex: opacityLabel=Opacidad: alphaLabel=Alpha: # not sure but I believe alpha should workcolorpicker-1.0.0/com/bric/swing/resources/ColorPicker_es.properties0000644000175000017500000000102111437472304025224 0ustar andrewandrew# # Copyright (c) 2008 Jeremy Wood # E-mail: mickleness@gmail.com # All rights reserved. # # The copyright of this software is owned by Jeremy Wood. # You may not use, copy or modify this software, except in # accordance with the license agreement you entered into with # Jeremy Wood. For details see accompanying license terms. # ColorPickerDialogTitle=Elegir Color Copy=Copiar blueLabel=Azul: greenLabel=Verde: redLabel=Rojo: brightnessLabel=Brillo: saturationLabel=Sat: hueLabel=Tinte: opacityLabel=Opacidad: alphaLabel=Alpha:colorpicker-1.0.0/com/bric/swing/resources/ColorPicker_en_GB.properties0000644000175000017500000000056111437472304025577 0ustar andrewandrew# # Copyright (c) 2008 Jeremy Wood # E-mail: mickleness@gmail.com # All rights reserved. # # The copyright of this software is owned by Jeremy Wood. # You may not use, copy or modify this software, except in # accordance with the license agreement you entered into with # Jeremy Wood. For details see accompanying license terms. # ColorPickerDialogTitle=Choose a Colourcolorpicker-1.0.0/com/bric/swing/resources/ColorPicker_de.properties0000644000175000017500000000104211437472304025210 0ustar andrewandrew# # Copyright (c) 2008 Jeremy Wood # E-mail: mickleness@gmail.com # All rights reserved. # # The copyright of this software is owned by Jeremy Wood. # You may not use, copy or modify this software, except in # accordance with the license agreement you entered into with # Jeremy Wood. For details see accompanying license terms. # ColorPickerDialogTitle=Farbauswahl Copy=Kopieren blueLabel=Blau: greenLabel=Grün: redLabel=Rot: brightnessLabel=Helligkeit: saturationLabel=Sättigung: hueLabel=Farbton: opacityLabel=Deckkraft: alphaLabel=Alphakanal:colorpicker-1.0.0/com/bric/swing/resources/DialogFooter.properties0000644000175000017500000000044511437472304024710 0ustar andrewandrewdialogCancelButton=Cancel dialogOKButton=OK dialogSaveButton=Save dialogDontSaveButton=Don't Save dialogYesButton=Yes dialogNoButton=No dialogCancelMnemonic=C dialogOKMnemonic=O dialogSaveMnemonic=S dialogDontSaveMnemonic=D dialogYesMnemonic=Y dialogNoMnemonic=N dialogHelpLearnMore=Learn Morecolorpicker-1.0.0/com/bric/swing/resources/ColorPicker_nl.properties0000644000175000017500000000133111437472304025232 0ustar andrewandrew# # Copyright (c) 2008 Jeremy Wood # E-mail: mickleness@gmail.com # All rights reserved. # # The copyright of this software is owned by Jeremy Wood. # You may not use, copy or modify this software, except in # accordance with the license agreement you entered into with # Jeremy Wood. For details see accompanying license terms. # ColorPickerDialogTitle=Kies de kleur Copy=Kopiëren # or 'copy' blueLabel=Blauw: greenLabel=Groen: redLabel=Rood: brightnessLabel=Helderheid: hueLabel=Hue: # or tint: 'tint' ; color spread: 'kleur(schakeriung)' saturationLabel=Saturatie: # 'kleur Intensiteit' which means color intensity hexLabel=Hex: opacityLabel=ondoorzichtigheid: # or 'Opaciteit' alphaLabel=doorzichtigheid: #or 'transparantie'colorpicker-1.0.0/com/bric/swing/resources/ColorPicker_fr.properties0000644000175000017500000000111611437472304025231 0ustar andrewandrew# # Copyright (c) 2008 Jeremy Wood # E-mail: mickleness@gmail.com # All rights reserved. # # The copyright of this software is owned by Jeremy Wood. # You may not use, copy or modify this software, except in # accordance with the license agreement you entered into with # Jeremy Wood. For details see accompanying license terms. # ColorPickerDialogTitle=Choisissez une couleur Copy=Copier blueLabel=Bleu: greenLabel=Vert: redLabel=Rouge: brightnessLabel=Luminosité: hueLabel=Teinte: saturationLabel=Saturation: hexLabel=Hex: opacityLabel=Opacité: alphaLabel=Tranparence: # Alpha works too !colorpicker-1.0.0/com/bric/swing/resources/DialogFooter_fr.properties0000644000175000017500000000012311437472304025370 0ustar andrewandrewdialogCancelButton=Annuler dialogOKButton=OK dialogNoButton=Non dialogYesButton=Ouicolorpicker-1.0.0/com/bric/swing/ColorPickerDialog.java0000644000175000017500000000562211437472304022403 0ustar andrewandrew/* * @(#)ColorPickerDialog.java * * $Date: 2010-05-27 02:49:03 -0500 (Thu, 27 May 2010) $ * * Copyright (c) 2009 by Jeremy Wood. * All rights reserved. * * The copyright of this software is owned by Jeremy Wood. * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * Jeremy Wood. For details see accompanying license terms. * * This software is probably, but not necessarily, discussed here: * http://javagraphics.blogspot.com/ * * And the latest version should be available here: * https://javagraphics.dev.java.net/ */ package com.bric.swing; import java.awt.Color; import java.awt.Component; import java.awt.Dialog; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JComponent; import javax.swing.JDialog; /** This wraps a ColorPicker in a simple dialog with "OK" and "Cancel" options. *

(This object is used by the static calls in ColorPicker to show a dialog.) * */ class ColorPickerDialog extends JDialog { private static final long serialVersionUID = 2L; ColorPicker cp; int alpha; Color returnValue = null; ActionListener okListener = new ActionListener() { public void actionPerformed(ActionEvent e) { returnValue = cp.getColor(); } }; DialogFooter footer; public ColorPickerDialog(Frame owner, Color color,boolean includeOpacity) { super(owner); initialize(owner,color,includeOpacity); } public ColorPickerDialog(Dialog owner, Color color,boolean includeOpacity) { super(owner); initialize(owner,color,includeOpacity); } private void initialize(Component owner,Color color,boolean includeOpacity) { cp = new ColorPicker(true,includeOpacity); setModal(true); setResizable(false); getContentPane().setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.gridx = 0; c.gridy = 0; c.weightx = 1; c.weighty = 1; c.fill = GridBagConstraints.BOTH; c.gridwidth = GridBagConstraints.REMAINDER; c.insets = new Insets(10,10,10,10); getContentPane().add(cp,c); c.gridy++; footer = DialogFooter.createDialogFooter(new JComponent[] {}, DialogFooter.OK_CANCEL_OPTION, DialogFooter.OK_OPTION, DialogFooter.ESCAPE_KEY_TRIGGERS_CANCEL); c.gridy++; c.weighty = 0; getContentPane().add(footer, c); cp.setRGB(color.getRed(), color.getGreen(), color.getBlue()); cp.setOpacity( color.getAlpha() ); alpha = color.getAlpha(); pack(); setLocationRelativeTo(owner); footer.getButton(DialogFooter.OK_OPTION).addActionListener(okListener); } /** @return the color committed when the user clicked 'OK'. Note this returns null * if the user canceled this dialog, or exited via the close decoration. */ public Color getColor() { return returnValue; } } colorpicker-1.0.0/com/bric/swing/DelegateFocusTraversalPolicy.java0000644000175000017500000000330011437472304024614 0ustar andrewandrew/* * @(#)DelegateFocusTraversalPolicy.java * * $Date: 2010-03-19 18:47:16 -0500 (Fri, 19 Mar 2010) $ * * Copyright (c) 2010 by Jeremy Wood. * All rights reserved. * * The copyright of this software is owned by Jeremy Wood. * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * Jeremy Wood. For details see accompanying license terms. * * This software is probably, but not necessarily, discussed here: * https://javagraphics.dev.java.net/ * * That site should also contain the most recent official version * of this software. (See the SVN repository for more details.) */ package com.bric.swing; import java.awt.Component; import java.awt.Container; import java.awt.FocusTraversalPolicy; /** A simple FocusTraversalPolicy object that delegates to * another object. * */ public class DelegateFocusTraversalPolicy extends FocusTraversalPolicy { FocusTraversalPolicy ftp; public DelegateFocusTraversalPolicy(FocusTraversalPolicy policy) { ftp = policy; } public Component getComponentAfter(Container focusCycleRoot, Component component) { return ftp.getComponentAfter(focusCycleRoot, component); } public Component getComponentBefore(Container focusCycleRoot, Component component) { return ftp.getComponentBefore(focusCycleRoot, component); } public Component getDefaultComponent(Container focusCycleRoot) { return ftp.getDefaultComponent(focusCycleRoot); } public Component getFirstComponent(Container focusCycleRoot) { return ftp.getFirstComponent(focusCycleRoot); } public Component getLastComponent(Container focusCycleRoot) { return ftp.getLastComponent(focusCycleRoot); } } colorpicker-1.0.0/com/bric/swing/ColorSwatch.java0000644000175000017500000000777411437472304021311 0ustar andrewandrew/* * @(#)ColorSwatch.java * * $Date: 2010-03-19 19:27:24 -0500 (Fri, 19 Mar 2010) $ * * Copyright (c) 2009 by Jeremy Wood. * All rights reserved. * * The copyright of this software is owned by Jeremy Wood. * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * Jeremy Wood. For details see accompanying license terms. * * This software is probably, but not necessarily, discussed here: * http://javagraphics.blogspot.com/ * * And the latest version should be available here: * https://javagraphics.dev.java.net/ */ package com.bric.swing; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.TexturePaint; import java.awt.Toolkit; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import com.bric.plaf.PlafPaintUtils; /** This is a square, opaque panel used to indicate * a certain color. *

The color is assigned with the setForeground() method. *

Also the user can right-click this panel and select 'Copy' to send * a 100x100 image of this color to the clipboard. (This feature was * added at the request of a friend who paints; she wanted to select a * color and then quickly print it off, and then mix her paints to match * that shade.) * */ public class ColorSwatch extends JPanel { private static final long serialVersionUID = 1L; JPopupMenu menu; JMenuItem copyItem; MouseListener mouseListener = new MouseAdapter() { public void mousePressed(MouseEvent e) { if(e.isPopupTrigger()) { if(menu==null) { menu = new JPopupMenu(); copyItem = new JMenuItem(ColorPicker.strings.getObject("Copy").toString()); menu.add(copyItem); copyItem.addActionListener(actionListener); } menu.show(ColorSwatch.this,e.getX(),e.getY()); } } }; ActionListener actionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if(src==copyItem) { BufferedImage image = new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); g.setColor(getBackground()); g.fillRect(0, 0, image.getWidth(), image.getHeight()); g.dispose(); Transferable contents = new ImageTransferable(image); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(contents, null); } } }; int w; public ColorSwatch(int width) { w = width; setPreferredSize(new Dimension(width,width)); setMinimumSize(new Dimension(width,width)); addMouseListener(mouseListener); } public ColorSwatch(Color color,int width) { this(width); setForeground(color); } private static TexturePaint checkerPaint = null; private static TexturePaint getCheckerPaint() { if(checkerPaint==null) { int t = 8; BufferedImage bi = new BufferedImage(t*2,t*2,BufferedImage.TYPE_INT_RGB); Graphics g = bi.createGraphics(); g.setColor(Color.white); g.fillRect(0,0,2*t,2*t); g.setColor(Color.lightGray); g.fillRect(0,0,t,t); g.fillRect(t,t,t,t); checkerPaint = new TexturePaint(bi,new Rectangle(0,0,bi.getWidth(),bi.getHeight())); } return checkerPaint; } public void paint(Graphics g0) { super.paint(g0); //may be necessary for some look-and-feels? Graphics2D g = (Graphics2D)g0; Color c = getForeground(); int w2 = Math.min(getWidth(), w); int h2 = Math.min(getHeight(), w); Rectangle r = new Rectangle(getWidth()/2-w2/2,getHeight()/2-h2/2, w2, h2); if(c.getAlpha()<255) { TexturePaint checkers = getCheckerPaint(); g.setPaint(checkers); g.fillRect(r.x, r.y, r.width, r.height); } g.setColor(c); g.fillRect(r.x, r.y, r.width, r.height); PlafPaintUtils.drawBevel(g, r); } } colorpicker-1.0.0/com/bric/swing/ColorPickerPanel.java0000644000175000017500000004520211437472304022241 0ustar andrewandrew/* * @(#)ColorPickerPanel.java * * $Date: 2010-03-19 19:27:24 -0500 (Fri, 19 Mar 2010) $ * * Copyright (c) 2009 by Jeremy Wood. * All rights reserved. * * The copyright of this software is owned by Jeremy Wood. * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * Jeremy Wood. For details see accompanying license terms. * * This software is probably, but not necessarily, discussed here: * http://javagraphics.blogspot.com/ * * And the latest version should be available here: * https://javagraphics.dev.java.net/ */ package com.bric.swing; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.util.Vector; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.MouseInputAdapter; import javax.swing.event.MouseInputListener; import com.bric.plaf.PlafPaintUtils; /** This is the large graphic element in the ColorPicker * that depicts a wide range of colors. *

This panel can operate in 6 different modes. In each mode a different * property is held constant: hue, saturation, brightness, red, green, or blue. * (Each property is identified with a constant in the ColorPicker class, * such as: ColorPicker.HUE or ColorPicker.GREEN.) *

In saturation and brightness mode, a wheel is used. Although it doesn't * use as many pixels as a square does: it is a very aesthetic model since the hue can * wrap around in a complete circle. (Also, on top of looks, this is how most * people learn to think the color spectrum, so it has that advantage, too). * In all other modes a square is used. *

The user can click in this panel to select a new color. The selected color is * highlighted with a circle drawn around it. Also once this * component has the keyboard focus, the user can use the arrow keys to * traverse the available colors. *

Note this component is public and exists independently of the * ColorPicker class. The only way this class is dependent * on the ColorPicker class is when the constants for the modes * are used. *

The graphic in this panel will be based on either the width or * the height of this component: depending on which is smaller. * */ public class ColorPickerPanel extends JPanel { private static final long serialVersionUID = 1L; /** The maximum size the graphic will be. No matter * how big the panel becomes, the graphic will not exceed * this length. *

(This is enforced because only 1 BufferedImage is used * to render the graphic. This image is created once at a fixed * size and is never replaced.) */ public static final int MAX_SIZE = 325; /** This controls how the colors are displayed. */ private int mode = ColorPicker.BRI; /** The point used to indicate the selected color. */ private Point point = new Point(0,0); private Vector changeListeners = new Vector(); /* Floats from [0,1]. They must be kept distinct, because * when you convert them to RGB coordinates HSB(0,0,0) and HSB (.5,0,0) * and then convert them back to HSB coordinates, the hue always shifts back to zero. */ float hue = -1, sat = -1, bri = -1; int red = -1, green = -1, blue = -1; MouseInputListener mouseListener = new MouseInputAdapter() { public void mousePressed(MouseEvent e) { requestFocus(); Point p = e.getPoint(); if(mode==ColorPicker.BRI || mode==ColorPicker.SAT || mode==ColorPicker.HUE) { float[] hsb = getHSB(p); setHSB(hsb[0], hsb[1], hsb[2]); } else { int[] rgb = getRGB(p); setRGB(rgb[0], rgb[1], rgb[2]); } } public void mouseDragged(MouseEvent e) { mousePressed(e); } }; KeyListener keyListener = new KeyAdapter() { public void keyPressed(KeyEvent e) { int dx = 0; int dy = 0; if(e.getKeyCode()==KeyEvent.VK_LEFT) { dx = -1; } else if(e.getKeyCode()==KeyEvent.VK_RIGHT) { dx = 1; } else if(e.getKeyCode()==KeyEvent.VK_UP) { dy = -1; } else if(e.getKeyCode()==KeyEvent.VK_DOWN) { dy = 1; } int multiplier = 1; if(e.isShiftDown() && e.isAltDown()) { multiplier = 10; } else if(e.isShiftDown() || e.isAltDown()) { multiplier = 5; } if(dx!=0 || dy!=0) { int size = Math.min(MAX_SIZE, Math.min(getWidth()-imagePadding.left-imagePadding.right,getHeight()-imagePadding.top-imagePadding.bottom)); int offsetX = getWidth()/2-size/2; int offsetY = getHeight()/2-size/2; mouseListener.mousePressed(new MouseEvent(ColorPickerPanel.this, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), 0, point.x+multiplier*dx+offsetX, point.y+multiplier*dy+offsetY, 1, false )); } } }; FocusListener focusListener = new FocusListener() { public void focusGained(FocusEvent e) { repaint(); } public void focusLost(FocusEvent e) { repaint(); } }; ComponentListener componentListener = new ComponentAdapter() { public void componentResized(ComponentEvent e) { regeneratePoint(); regenerateImage(); } }; BufferedImage image = new BufferedImage(MAX_SIZE, MAX_SIZE, BufferedImage.TYPE_INT_ARGB); /** Creates a new ColorPickerPanel */ public ColorPickerPanel() { setMaximumSize(new Dimension(MAX_SIZE+imagePadding.left+imagePadding.right, MAX_SIZE+imagePadding.top+imagePadding.bottom)); setPreferredSize(new Dimension( (int)(MAX_SIZE*.75), (int)(MAX_SIZE*.75))); setRGB(0,0,0); addMouseListener(mouseListener); addMouseMotionListener(mouseListener); setFocusable(true); addKeyListener(keyListener); addFocusListener(focusListener); setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); addComponentListener(componentListener); } /** This listener will be notified when the current HSB or RGB values * change. */ public void addChangeListener(ChangeListener l) { if(changeListeners.contains(l)) return; changeListeners.add(l); } /** Remove a ChangeListener so it is no longer * notified when the selected color changes. */ public void removeChangeListener(ChangeListener l) { changeListeners.remove(l); } protected void fireChangeListeners() { if(changeListeners==null) return; for(int a = 0; aColorPicker class: * HUE, SAT, BRI, RED, GREEN, or BLUE */ public void setMode(int mode) { if(!(mode==ColorPicker.HUE || mode==ColorPicker.SAT || mode==ColorPicker.BRI || mode==ColorPicker.RED || mode==ColorPicker.GREEN || mode==ColorPicker.BLUE)) throw new IllegalArgumentException("The mode must be HUE, SAT, BRI, RED, GREEN, or BLUE."); if(this.mode==mode) return; this.mode = mode; regenerateImage(); regeneratePoint(); } /** Sets the selected color of this panel. *

If this panel is in HUE, SAT, or BRI mode, then * this method converts these values to HSB coordinates * and calls setHSB. *

This method may regenerate the graphic if necessary. * * @param r the red value of the selected color. * @param g the green value of the selected color. * @param b the blue value of the selected color. */ public void setRGB(int r,int g,int b) { if(r<0 || r>255) throw new IllegalArgumentException("The red value ("+r+") must be between [0,255]."); if(g<0 || g>255) throw new IllegalArgumentException("The green value ("+g+") must be between [0,255]."); if(b<0 || b>255) throw new IllegalArgumentException("The blue value ("+b+") must be between [0,255]."); if(red!=r || green!=g || blue!=b) { if(mode==ColorPicker.RED || mode==ColorPicker.GREEN || mode==ColorPicker.BLUE) { int lastR = red; int lastG = green; int lastB = blue; red = r; green = g; blue = b; if(mode==ColorPicker.RED) { if(lastR!=r) { regenerateImage(); } } else if(mode==ColorPicker.GREEN) { if(lastG!=g) { regenerateImage(); } } else if(mode==ColorPicker.BLUE) { if(lastB!=b) { regenerateImage(); } } } else { float[] hsb = new float[3]; Color.RGBtoHSB(r, g, b, hsb); setHSB(hsb[0],hsb[1],hsb[2]); return; } regeneratePoint(); repaint(); fireChangeListeners(); } } /** @return the HSB values of the selected color. * Each value is between [0,1]. */ public float[] getHSB() { return new float[] {hue, sat, bri}; } /** @return the RGB values of the selected color. * Each value is between [0,255]. */ public int[] getRGB() { return new int[] {red, green, blue}; } /** Returns the color at the indicated point in HSB values. * * @param p a point relative to this panel. * @return the HSB values at the point provided. */ public float[] getHSB(Point p) { if(mode==ColorPicker.RED || mode==ColorPicker.GREEN || mode==ColorPicker.BLUE) { int[] rgb = getRGB(p); float[] hsb = Color.RGBtoHSB(rgb[0], rgb[1], rgb[2], null); return hsb; } int size = Math.min(MAX_SIZE, Math.min(getWidth()-imagePadding.left-imagePadding.right,getHeight()-imagePadding.top-imagePadding.bottom)); p.translate(-(getWidth()/2-size/2), -(getHeight()/2-size/2)); if(mode==ColorPicker.BRI || mode==ColorPicker.SAT) { //the two circular views: double radius = ((double)size)/2.0; double x = p.getX()-size/2.0; double y = p.getY()-size/2.0; double r = Math.sqrt(x*x+y*y)/radius; double theta = Math.atan2(y,x)/(Math.PI*2.0); if(r>1) r = 1; if(mode==ColorPicker.BRI) { return new float[] { (float)(theta+.25f), (float)(r), bri}; } else { return new float[] { (float)(theta+.25f), sat, (float)(r) }; } } else { float s = ((float)p.x)/((float)size); float b = ((float)p.y)/((float)size); if(s<0) s = 0; if(s>1) s = 1; if(b<0) b = 0; if(b>1) b = 1; return new float[] {hue, s, b}; } } /** Returns the color at the indicated point in RGB values. * * @param p a point relative to this panel. * @return the RGB values at the point provided. */ public int[] getRGB(Point p) { if(mode==ColorPicker.BRI || mode==ColorPicker.SAT || mode==ColorPicker.HUE) { float[] hsb = getHSB(p); int rgb = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]); int r = (rgb & 0xff0000) >> 16; int g = (rgb & 0xff00) >> 8; int b = (rgb & 0xff); return new int[] {r, g, b}; } int size = Math.min(MAX_SIZE, Math.min(getWidth()-imagePadding.left-imagePadding.right,getHeight()-imagePadding.top-imagePadding.bottom)); p.translate(-(getWidth()/2-size/2), -(getHeight()/2-size/2)); int x2 = p.x*255/size; int y2 = p.y*255/size; if(x2<0) x2 = 0; if(x2>255) x2 = 255; if(y2<0) y2 = 0; if(y2>255) y2 = 255; if(mode==ColorPicker.RED) { return new int[] {red, x2, y2}; } else if(mode==ColorPicker.GREEN) { return new int[] {x2, green, y2}; } else { return new int[] {x2, y2, blue}; } } /** Sets the selected color of this panel. *

If this panel is in RED, GREEN, or BLUE mode, then * this method converts these values to RGB coordinates * and calls setRGB. *

This method may regenerate the graphic if necessary. * * @param h the hue value of the selected color. * @param s the saturation value of the selected color. * @param b the brightness value of the selected color. */ public void setHSB(float h,float s,float b) { //hue is cyclic: it can be any value h = (float)(h-Math.floor(h)); if(s<0 || s>1) throw new IllegalArgumentException("The saturation value ("+s+") must be between [0,1]"); if(b<0 || b>1) throw new IllegalArgumentException("The brightness value ("+b+") must be between [0,1]"); if(hue!=h || sat!=s || bri!=b) { if(mode==ColorPicker.HUE || mode==ColorPicker.BRI || mode==ColorPicker.SAT) { float lastHue = hue; float lastBri = bri; float lastSat = sat; hue = h; sat = s; bri = b; if(mode==ColorPicker.HUE) { if(lastHue!=hue) { regenerateImage(); } } else if(mode==ColorPicker.SAT) { if(lastSat!=sat) { regenerateImage(); } } else if(mode==ColorPicker.BRI) { if(lastBri!=bri) { regenerateImage(); } } } else { Color c = new Color(Color.HSBtoRGB(h, s, b)); setRGB(c.getRed(), c.getGreen(), c.getBlue()); return; } Color c = new Color(Color.HSBtoRGB(hue, sat, bri)); red = c.getRed(); green = c.getGreen(); blue = c.getBlue(); regeneratePoint(); repaint(); fireChangeListeners(); } } /** Recalculates the (x,y) point used to indicate the selected color. */ private void regeneratePoint() { int size = Math.min(MAX_SIZE, Math.min(getWidth()-imagePadding.left-imagePadding.right,getHeight()-imagePadding.top-imagePadding.bottom)); if(mode==ColorPicker.HUE || mode==ColorPicker.SAT || mode==ColorPicker.BRI) { if(mode==ColorPicker.HUE) { point = new Point((int)(sat*size+.5),(int)(bri*size+.5)); } else if(mode==ColorPicker.SAT) { double theta = hue*2*Math.PI-Math.PI/2; if(theta<0) theta+=2*Math.PI; double r = bri*size/2; point = new Point((int)(r*Math.cos(theta)+.5+size/2.0),(int)(r*Math.sin(theta)+.5+size/2.0)); } else if(mode==ColorPicker.BRI) { double theta = hue*2*Math.PI-Math.PI/2; if(theta<0) theta+=2*Math.PI; double r = sat*size/2; point = new Point((int)(r*Math.cos(theta)+.5+size/2.0),(int)(r*Math.sin(theta)+.5+size/2.0)); } } else if(mode==ColorPicker.RED) { point = new Point((int)(green*size/255f+.49f), (int)(blue*size/255f+.49f) ); } else if(mode==ColorPicker.GREEN) { point = new Point((int)(red*size/255f+.49f), (int)(blue*size/255f+.49f) ); } else if(mode==ColorPicker.BLUE) { point = new Point((int)(red*size/255f+.49f), (int)(green*size/255f+.49f) ); } } /** A row of pixel data we recycle every time we regenerate this image. */ private int[] row = new int[MAX_SIZE]; /** Regenerates the image. */ private synchronized void regenerateImage() { int size = Math.min(MAX_SIZE, Math.min(getWidth()-imagePadding.left-imagePadding.right,getHeight()-imagePadding.top-imagePadding.bottom)); if(mode==ColorPicker.BRI || mode==ColorPicker.SAT) { float bri2 = this.bri; float sat2 = this.sat; float radius = ((float)size)/2f; float hue2; float k = 1.2f; //the number of pixels to antialias for(int y = 0; yradius-k) { int alpha = (int)(255-255*(r-radius+k)/k); if(alpha<0) alpha = 0; if(alpha>255) alpha = 255; row[x] = row[x] & 0xffffff+(alpha << 24); } } else { row[x] = 0x00000000; } } image.getRaster().setDataElements(0, y, size, 1, row); } } else if(mode==ColorPicker.HUE) { float hue2 = this.hue; for(int y = 0; yYou can pull some parts of it apart for customization, but out-of-the-box it offers a great interface if you're dealing with a power user. *

Of course: all dialogs are at least slightly evil, and they should be used with care... * @see Colors: a Color Dialog */ public class ColorPickerDemo extends JApplet implements PropertyChangeListener { private static final long serialVersionUID = 1L; public static BufferedImage createBlurbGraphic(Dimension preferredSize) throws Exception { ColorPicker picker = new ColorPicker(); picker.setColor(new Color(0x4F63C3)); JFrame frame = new JFrame(); final JInternalFrame window = new JInternalFrame(); window.getContentPane().add(picker); window.pack(); frame.getContentPane().add(window); frame.pack(); final BufferedImage image = new BufferedImage(window.getWidth(), window.getHeight(), BufferedImage.TYPE_INT_ARGB); SwingUtilities.invokeAndWait(new Runnable() { public void run() { Graphics2D g = image.createGraphics(); window.paint(g); g.dispose(); } }); return image; } /** This demonstrates how to customize a small ColorPicker component. */ public static void main(String[] args) { final JFrame demo = new JFrame("Demo"); final JWindow palette = new JWindow(demo); final ColorPicker picker = new ColorPicker(true,false); final JComboBox comboBox = new JComboBox(); final JCheckBox alphaCheckbox = new JCheckBox("Include Alpha"); final JCheckBox hsbCheckbox = new JCheckBox("Include HSB Values"); final JCheckBox rgbCheckbox = new JCheckBox("Include RGB Values"); final JCheckBox modeCheckbox = new JCheckBox("Include Mode Controls",true); final JButton button = new JButton("Show Dialog"); demo.getContentPane().setLayout(new GridBagLayout()); palette.getContentPane().setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.gridx = 0; c.gridy = 0; c.weightx = 1; c.weighty = 0; c.insets = new Insets(5,5,5,5); c.anchor = GridBagConstraints.WEST; palette.getContentPane().add(comboBox,c); c.gridy++; palette.getContentPane().add(alphaCheckbox,c); c.gridy++; palette.getContentPane().add(hsbCheckbox,c); c.gridy++; palette.getContentPane().add(rgbCheckbox,c); c.gridy++; palette.getContentPane().add(modeCheckbox,c); c.gridy = 0; c.weighty = 1; c.fill = GridBagConstraints.BOTH; picker.setPreferredSize(new Dimension(220,200)); demo.getContentPane().add(picker,c); c.gridy++; c.weighty = 0; demo.getContentPane().add(picker.getExpertControls(),c); c.gridy++; c.fill = GridBagConstraints.NONE; demo.getContentPane().add(button,c); comboBox.addItem("Hue"); comboBox.addItem("Saturation"); comboBox.addItem("Brightness"); comboBox.addItem("Red"); comboBox.addItem("Green"); comboBox.addItem("Blue"); ActionListener checkboxListener = new ActionListener() { public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if(src==alphaCheckbox) { picker.setOpacityVisible(alphaCheckbox.isSelected()); } else if(src==hsbCheckbox) { picker.setHSBControlsVisible(hsbCheckbox.isSelected()); } else if(src==rgbCheckbox) { picker.setRGBControlsVisible(rgbCheckbox.isSelected()); } else if(src==modeCheckbox) { picker.setModeControlsVisible(modeCheckbox.isSelected()); } demo.pack(); } }; picker.setOpacityVisible(false); picker.setHSBControlsVisible(false); picker.setRGBControlsVisible(false); picker.setHexControlsVisible(false); picker.setPreviewSwatchVisible(false); picker.addPropertyChangeListener(ColorPicker.MODE_PROPERTY, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { int m = picker.getMode(); if(m==ColorPicker.HUE) { comboBox.setSelectedIndex(0); } else if(m==ColorPicker.SAT) { comboBox.setSelectedIndex(1); } else if(m==ColorPicker.BRI) { comboBox.setSelectedIndex(2); } else if(m==ColorPicker.RED) { comboBox.setSelectedIndex(3); } else if(m==ColorPicker.GREEN) { comboBox.setSelectedIndex(4); } else if(m==ColorPicker.BLUE) { comboBox.setSelectedIndex(5); } } }); alphaCheckbox.addActionListener(checkboxListener); hsbCheckbox.addActionListener(checkboxListener); rgbCheckbox.addActionListener(checkboxListener); modeCheckbox.addActionListener(checkboxListener); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Color color = picker.getColor(); color = ColorPicker.showDialog(demo, color, true); if(color!=null) picker.setColor(color); } }); comboBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int i = ((JComboBox)e.getSource()).getSelectedIndex(); if(i==0) { picker.setMode(ColorPicker.HUE); } else if(i==1) { picker.setMode(ColorPicker.SAT); } else if(i==2) { picker.setMode(ColorPicker.BRI); } else if(i==3) { picker.setMode(ColorPicker.RED); } else if(i==4) { picker.setMode(ColorPicker.GREEN); } else if(i==5) { picker.setMode(ColorPicker.BLUE); } } }); comboBox.setSelectedIndex(2); palette.pack(); palette.setLocationRelativeTo(null); demo.addComponentListener(new ComponentAdapter() { public void componentMoved(ComponentEvent e) { Point p = demo.getLocation(); palette.setLocation(new Point(p.x-palette.getWidth()-10,p.y)); } }); demo.pack(); demo.setLocationRelativeTo(null); demo.setVisible(true); palette.setVisible(true); demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public ColorPickerDemo() { try { String lf = UIManager.getSystemLookAndFeelClassName(); UIManager.setLookAndFeel(lf); } catch (Throwable e) { e.printStackTrace(); } ColorPicker picker = new ColorPicker(); picker.setOpacityVisible(true); Random r = new Random(System.currentTimeMillis()); picker.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255))); getContentPane().add(picker); picker.addPropertyChangeListener(this); /* If you really want to know what RGB values the mouse is over: ColorPickerPanel pickerPanel = picker.getColorPanel(); pickerPanel.addMouseMotionListener(new MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { ColorPickerPanel cpp = (ColorPickerPanel)e.getSource(); int[] rgb = cpp.getRGB(e.getPoint()); System.out.println("indicated point: "+rgb[0]+", "+rgb[1]+", "+rgb[2]); } }); */ picker.setBackground(Color.white); picker.setOpaque(true); } public void propertyChange(PropertyChangeEvent evt) { System.out.println("\""+evt.getPropertyName()+"\" "+toString(evt.getOldValue())+"->"+toString(evt.getNewValue())); } /** Because Color.toString() omits alpha information... * * @param obj * @return */ private static String toString(Object obj) { if(obj==null) return null; if(obj instanceof Color) { Color c = (Color)obj; return "Color[ r="+c.getRed()+", g="+c.getGreen()+", b="+c.getBlue()+", a="+c.getAlpha()+"]"; } return obj.toString(); } } colorpicker-1.0.0/com/bric/swing/DialogFooter.java0000644000175000017500000011373511437472304021432 0ustar andrewandrew/* * @(#)DialogFooter.java * * $Date: 2010-06-25 13:49:43 -0500 (Fri, 25 Jun 2010) $ * * Copyright (c) 2009 by Jeremy Wood. * All rights reserved. * * The copyright of this software is owned by Jeremy Wood. * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * Jeremy Wood. For details see accompanying license terms. * * This software is probably, but not necessarily, discussed here: * http://javagraphics.blogspot.com/ * * And the latest version should be available here: * https://javagraphics.dev.java.net/ */ package com.bric.swing; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.lang.reflect.Method; import java.util.ResourceBundle; import java.util.Vector; import javax.swing.AbstractAction; import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JRootPane; import javax.swing.KeyStroke; import javax.swing.RootPaneContainer; import javax.swing.SwingUtilities; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; import com.bric.plaf.FocusArrowListener; import com.bric.util.JVM; /** This is a row of buttons, intended to be displayed at the * bottom of a dialog. This class is strongly related to the * {@link com.bric.swing.QDialog} project, although the * DialogFooter can exist by itself. *

On the left of a footer are controls that should apply to the dialog itself, * such as "Help" button, or a "Reset Preferences" button. * On the far right are buttons that should dismiss this dialog. They * may be presented in different orders on different platforms based * on the reverseButtonOrder boolean. *

Buttons are also generally normalized, so the widths of buttons * are equal. *

This object will "latch onto" the RootPane that contains it. It is assumed * two DialogFooters will not be contained in the same RootPane. It is also * assumed the same DialogFooter will not be passed around to several * different RootPanes. *

Preset Options

* This class has several OPTION constants to create specific buttons. *

In each constant the first option is the default button unless * you specify otherwise. The Apple Interface Guidelines advises: * "The default button should be the button that represents the * action that the user is most likely to perform if that action isnŐt * potentially dangerous." *

The YES_NO options should be approached with special reluctance. * Microsoft cautions, * "Use Yes and No buttons only to respond to yes or no questions." This seems * obvious enough, but Apple adds, "Button names should correspond to the action * the user performs when pressing the buttonŃfor example, Erase, Save, or Delete." * So instead of presenting a YES_NO dialog with the question "Do you want to continue?" * a better dialog might provide the options "Cancel" and "Continue". In short: we * as developers might tend to lazily use this option and phrase dialogs in such * a way that yes/no options make sense, but in fact the commit buttons should be * more descriptive. *

Partly because of the need to avoid yes/no questions, DialogFooter introduces the * dialog type: SAVE_DONT_SAVE_CANCEL_OPTION. This is mostly straightforward, but * there is one catch: on Mac the buttons * are reordered: "Save", "Cancel" and "Don't Save". This is to conform with standard * Mac behavior. (Or, more specifically: because the Apple guidelines * state that a button that can cause permanent data loss be as physically far * from a "safe" button as possible.) On all other platforms the buttons are * listed in the order "Save", "Don't Save" and "Cancel". *

Also note the field {@link #reverseButtonOrder} * controls the order each option is presented in the dialog from left-to-right. *

Platform Differences

* These are based mostly on studying Apple and Vista interface guidelines. *
  • On Mac, command-period acts like the escape key in dialogs. *
  • On Mac the Help component is the standard Mac help icon. On other platforms * the help component is a {@link com.bric.swing.JLink}. *
  • By default button order is reversed on Macs compared to other platforms. See * the DialogFooter.reverseButtonOrder field for details. *
  • There is a static boolean to control whether button mnemonics should be * universally activated. This was added because * when studying Windows XP there seemed to be no fixed rules for whether to * use mnemonics or not. (Some dialogs show them, some dialogs don't.) So I * leave it to your discretion to activate them. I think this boolean should never be * activated on Vista or Mac, but on XP and Linux flavors: that's up to you. (Remember * using the alt key usually activates the mnemonics in most Java look-and-feels, so just * because they aren't universally active doesn't mean you're hurting accessibility needs.)
  • */ public class DialogFooter extends JPanel { private static final long serialVersionUID = 1L; /** This (the default behavior) does nothing when the escape key is pressed. */ public static final int ESCAPE_KEY_DOES_NOTHING = 0; /** This triggers the cancel button when the escape key is pressed. If no * cancel button is present: this does nothing. * (Also on Macs command+period acts the same as the escape key.) *

    This should only be used if the cancel button does not lead to data * loss, because users may quickly press the escape key before reading * the text in a dialog. */ public static final int ESCAPE_KEY_TRIGGERS_CANCEL = 1; /** This triggers the default button when the escape key is pressed. If no * default button is defined: this does nothing. * (Also on Macs command+period acts the same as the escape key.) *

    This should only be used if the default button does not lead to data * loss, because users may quickly press the escape key before reading * the text in a dialog. */ public static final int ESCAPE_KEY_TRIGGERS_DEFAULT = 2; /** This triggers the non-default button when the escape key is pressed. If no * non-default button is defined: this does nothing. * (Also on Macs command+period acts the same as the escape key.) *

    This should only be used if the non-default button does not lead to data * loss, because users may quickly press the escape key before reading * the text in a dialog. */ public static final int ESCAPE_KEY_TRIGGERS_NONDEFAULT = 3; private static KeyStroke escapeKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); private static KeyStroke commandPeriodKey = KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()); /** The localized strings used in dialogs. */ public static ResourceBundle strings = ResourceBundle.getBundle("com.bric.swing.resources.DialogFooter"); /** This is the client property of buttons created in static methods by this class. */ public static String PROPERTY_OPTION = "DialogFooter.propertyOption"; private static int uniqueCtr = 0; /** Used to indicate the user selected "Cancel" in a dialog. *
    Also this can be used as a dialog type, to indicate that "Cancel" should * be the only option presented to the user. *

    Note the usage is similar to JOptionPane's, but the numerical value is * different, so you cannot substitute JOptionPane.CANCEL_OPTION for DialogFooter.CANCEL_OPTION. */ public static final int CANCEL_OPTION = uniqueCtr++; /** Used to indicate the user selected "OK" in a dialog. *
    Also this can be used as a dialog type, to indicate that "OK" should * be the only option presented to the user. *

    Note the usage is similar to JOptionPane's, but the numerical value is * different, so you cannot substitute JOptionPane.OK_OPTION for DialogFooter.OK_OPTION. */ public static final int OK_OPTION = uniqueCtr++; /** Used to indicate the user selected "No" in a dialog. *
    Also this can be used as a dialog type, to indicate that "No" should * be the only option presented to the user. *

    Note the usage is similar to JOptionPane's, but the numerical value is * different, so you cannot substitute JOptionPane.NO_OPTION for DialogFooter.NO_OPTION. */ public static final int NO_OPTION = uniqueCtr++; /** Used to indicate the user selected "Yes" in a dialog. *
    Also this can be used as a dialog type, to indicate that "Yes" should * be the only option presented to the user. *

    Note the usage is similar to JOptionPane's, but the numerical value is * different, so you cannot substitute JOptionPane.YES_OPTION for DialogFooter.YES_OPTION. */ public static final int YES_OPTION = uniqueCtr++; /** Used to indicate a dialog should present a "Yes" and "No" option. *

    Note the usage is similar to JOptionPane's, but the numerical value is * different, so you cannot substitute JOptionPane.YES_NO_OPTION for DialogFooter.YES_NO_OPTION. */ public static final int YES_NO_OPTION = uniqueCtr++; /** Used to indicate a dialog should present a "Yes", "No", and "Cancel" option. *

    Note the usage is similar to JOptionPane's, but the numerical value is * different, so you cannot substitute JOptionPane.YES_NO_CANCEL_OPTION for DialogFooter.YES_NO_CANCEL_OPTION. */ public static final int YES_NO_CANCEL_OPTION = uniqueCtr++; /** Used to indicate a dialog should present a "OK" and "Cancel" option. *

    Note the usage is similar to JOptionPane's, but the numerical value is * different, so you cannot substitute JOptionPane.OK_CANCEL_OPTION for DialogFooter.OK_CANCEL_OPTION. */ public static final int OK_CANCEL_OPTION = uniqueCtr++; /** Used to indicate a dialog should present a "Save", "Don't Save", and "Cancel" option. */ public static final int SAVE_DONT_SAVE_CANCEL_OPTION = uniqueCtr++; /** Used to indicate the user selected "Save" in a dialog. *
    Also this can be used as a dialog type, to indicate that "Save" * should be the only option presented to the user. */ public static final int SAVE_OPTION = uniqueCtr++; /** Used to indicate the user selected "Don't Save" in a dialog. *
    Also this can be used as a dialog type, to indicate that "Don't Save" * should be the only option presented to the user. */ public static final int DONT_SAVE_OPTION = uniqueCtr++; private static AncestorListener escapeTriggerListener = new AncestorListener() { public void ancestorAdded(AncestorEvent event) { JButton button = (JButton)event.getComponent(); Window w = SwingUtilities.getWindowAncestor(button); if(w instanceof RootPaneContainer) { setRootPaneContainer(button, (RootPaneContainer)w); } else { setRootPaneContainer(button, null); } } private void setRootPaneContainer(JButton button,RootPaneContainer c) { RootPaneContainer lastContainer = (RootPaneContainer)button.getClientProperty("bric.footer.rpc"); if(lastContainer==c) return; if(lastContainer!=null) { lastContainer.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).remove(escapeKey); lastContainer.getRootPane().getActionMap().remove(escapeKey); if(JVM.isMac) lastContainer.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).remove(commandPeriodKey); } if(c!=null) { c.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(escapeKey, escapeKey); c.getRootPane().getActionMap().put(escapeKey, new ClickAction(button)); if(JVM.isMac) c.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(commandPeriodKey, escapeKey); } button.putClientProperty("bric.footer.rpc", c); } public void ancestorMoved(AncestorEvent event) { ancestorAdded(event); } public void ancestorRemoved(AncestorEvent event) { ancestorAdded(event); } }; /** Creates a new "Cancel" button. * * @param escapeKeyIsTrigger if true then pressing the escape * key will trigger this button. (Also on Macs command-period will act * like the escape key.) This should be false if this button * can lead to permanent data loss. */ public static JButton createCancelButton(boolean escapeKeyIsTrigger) { JButton button = new JButton(strings.getString("dialogCancelButton")); button.setMnemonic( strings.getString("dialogCancelMnemonic").charAt(0) ); button.putClientProperty(PROPERTY_OPTION, new Integer(CANCEL_OPTION)); if(escapeKeyIsTrigger) makeEscapeKeyActivate(button); return button; } /** This guarantees that when the escape key is pressed * (if its parent window has the keyboard focus) this button * is clicked. *

    It is assumed that no two buttons will try to consume * escape keys in the same window. * * @param button the button to trigger when the escape key is pressed. */ public static void makeEscapeKeyActivate(AbstractButton button) { button.addAncestorListener(escapeTriggerListener); } /** Creates a new "OK" button that is not triggered by the escape key. */ public static JButton createOKButton() { return createOKButton(false); } /** Creates a new "OK" button. * * @param escapeKeyIsTrigger if true then pressing the escape * key will trigger this button. (Also on Macs command-period will act * like the escape key.) This should be false if this button * can lead to permanent data loss. */ public static JButton createOKButton(boolean escapeKeyIsTrigger) { JButton button = new JButton(strings.getString("dialogOKButton")); button.setMnemonic( strings.getString("dialogOKMnemonic").charAt(0) ); button.putClientProperty(PROPERTY_OPTION, new Integer(OK_OPTION)); if(escapeKeyIsTrigger) makeEscapeKeyActivate(button); return button; } /** Creates a new "Yes" button that is not triggered by the escape key. */ public static JButton createYesButton() { return createYesButton(false); } /** Creates a new "Yes" button. * * @param escapeKeyIsTrigger if true then pressing the escape * key will trigger this button. (Also on Macs command-period will act * like the escape key.) This should be false if this button * can lead to permanent data loss. */ public static JButton createYesButton(boolean escapeKeyIsTrigger) { JButton button = new JButton(strings.getString("dialogYesButton")); button.setMnemonic( strings.getString("dialogYesMnemonic").charAt(0) ); button.putClientProperty(PROPERTY_OPTION, new Integer(YES_OPTION)); if(escapeKeyIsTrigger) makeEscapeKeyActivate(button); return button; } /** Creates a new "No" button that is not triggered by the escape key. * */ public static JButton createNoButton() { return createNoButton(false); } /** Creates a new "No" button. * * @param escapeKeyIsTrigger if true then pressing the escape * key will trigger this button. (Also on Macs command-period will act * like the escape key.) This should be false if this button * can lead to permanent data loss. */ public static JButton createNoButton(boolean escapeKeyIsTrigger) { JButton button = new JButton(strings.getString("dialogNoButton")); button.setMnemonic( strings.getString("dialogNoMnemonic").charAt(0) ); button.putClientProperty(PROPERTY_OPTION, new Integer(NO_OPTION)); if(escapeKeyIsTrigger) makeEscapeKeyActivate(button); return button; } /** Creates a new "Save" button that is not triggered by the escape key. */ public static JButton createSaveButton() { return createSaveButton(false); } /** Creates a new "Save" button. * * @param escapeKeyIsTrigger if true then pressing the escape * key will trigger this button. (Also on Macs command-period will act * like the escape key.) This should be false if this button * can lead to permanent data loss. */ public static JButton createSaveButton(boolean escapeKeyIsTrigger) { JButton button = new JButton(strings.getString("dialogSaveButton")); button.setMnemonic( strings.getString("dialogSaveMnemonic").charAt(0) ); button.putClientProperty(PROPERTY_OPTION, new Integer(SAVE_OPTION)); if(escapeKeyIsTrigger) makeEscapeKeyActivate(button); return button; } /** Creates a new "Don't Save" button that is not triggered by the escape key. */ public static JButton createDontSaveButton() { return createDontSaveButton(false); } /** Creates a new "Don't Save" button. * * @param escapeKeyIsTrigger if true then pressing the escape * key will trigger this button. (Also on Macs command-period will act * like the escape key.) This should be false if this button * can lead to permanent data loss. */ public static JButton createDontSaveButton(boolean escapeKeyIsTrigger) { String text = strings.getString("dialogDontSaveButton"); JButton button = new JButton(text); button.setMnemonic( strings.getString("dialogDontSaveMnemonic").charAt(0) ); button.putClientProperty(PROPERTY_OPTION, new Integer(DONT_SAVE_OPTION)); //Don't know if this documented by Apple, but command-D usually triggers "Don't Save" buttons: button.putClientProperty(DialogFooter.PROPERTY_META_SHORTCUT,new Character(text.charAt(0))); if(escapeKeyIsTrigger) makeEscapeKeyActivate(button); return button; } /** Creates a DialogFooter and assigns a default button. * The default button is the first button listed in the button type. For example, * a YES_NO_CANCEL_OPTION dialog will make the YES_OPTION the default button. *

    To use a different default button, use the other createDialogFooter() method. * * @param leftComponents the components to put on the left side of the footer. *

    The Apple guidelines state that this area is reserved for * "button[s] that affect the contents of the dialog itself, such as Reset [or Help]". * @param options one of the OPTIONS fields in this class, such as YES_NO_OPTION or CANCEL_OPTION. * @param escapeKeyBehavior one of the ESCAPE_KEY constants in this class. * @return a DialogFooter */ public static DialogFooter createDialogFooter(JComponent[] leftComponents,int options,int escapeKeyBehavior) { if(options==CANCEL_OPTION) { return createDialogFooter(leftComponents,options,CANCEL_OPTION,escapeKeyBehavior); } else if(options==DONT_SAVE_OPTION) { return createDialogFooter(leftComponents,options,DONT_SAVE_OPTION,escapeKeyBehavior); } else if(options==NO_OPTION) { return createDialogFooter(leftComponents,options,NO_OPTION,escapeKeyBehavior); } else if(options==OK_CANCEL_OPTION) { return createDialogFooter(leftComponents,options,OK_OPTION,escapeKeyBehavior); } else if(options==OK_OPTION) { return createDialogFooter(leftComponents,options,OK_OPTION,escapeKeyBehavior); } else if(options==SAVE_DONT_SAVE_CANCEL_OPTION) { return createDialogFooter(leftComponents,options,SAVE_OPTION,escapeKeyBehavior); } else if(options==SAVE_OPTION) { return createDialogFooter(leftComponents,options,SAVE_OPTION,escapeKeyBehavior); } else if(options==YES_NO_CANCEL_OPTION) { return createDialogFooter(leftComponents,options,YES_OPTION,escapeKeyBehavior); } else if(options==YES_NO_OPTION) { return createDialogFooter(leftComponents,options,YES_OPTION,escapeKeyBehavior); } else if(options==YES_OPTION) { return createDialogFooter(leftComponents,options,YES_OPTION,escapeKeyBehavior); } throw new IllegalArgumentException("unrecognized option type ("+options+")"); } /** Creates a DialogFooter. * @param leftComponents the components to put on the left side of the footer. *

    The Apple guidelines state that this area is reserved for * "button[s] that affect the contents of the dialog itself, such as Reset [or Help]". * @param options one of the OPTIONS fields in this class, such as YES_NO_OPTION or CANCEL_OPTION. * @param defaultButton the OPTION field corresponding to the button that * should be the default button, or -1 if there should be no default button. * @param escapeKeyBehavior one of the ESCAPE_KEY constants in this class. * @return a DialogFooter */ public static DialogFooter createDialogFooter(JComponent[] leftComponents,int options,int defaultButton,int escapeKeyBehavior) { JButton[] dismissControls; JButton cancelButton = null; JButton dontSaveButton = null; JButton noButton = null; JButton okButton = null; JButton saveButton = null; JButton yesButton = null; if(escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_NONDEFAULT) { int buttonCount = 1; if(options==OK_CANCEL_OPTION || options==YES_NO_OPTION) { buttonCount = 2; } else if(options==SAVE_DONT_SAVE_CANCEL_OPTION || options==YES_NO_CANCEL_OPTION) { buttonCount = 3; } if(defaultButton!=-1) { buttonCount--; } if(buttonCount>1) { throw new IllegalArgumentException("request for escape key to map to "+buttonCount+" buttons."); } } if(options==CANCEL_OPTION || options==OK_CANCEL_OPTION || options==SAVE_DONT_SAVE_CANCEL_OPTION || options==YES_NO_CANCEL_OPTION) { cancelButton = createCancelButton( escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_CANCEL || (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_NONDEFAULT && defaultButton!=CANCEL_OPTION) || (defaultButton==CANCEL_OPTION && escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_DEFAULT) ); } if(options==DONT_SAVE_OPTION || options==SAVE_DONT_SAVE_CANCEL_OPTION) { dontSaveButton = createDontSaveButton( (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_NONDEFAULT && defaultButton!=DONT_SAVE_OPTION) || (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_DEFAULT && defaultButton==DONT_SAVE_OPTION )); } if(options==NO_OPTION || options==YES_NO_OPTION || options==YES_NO_CANCEL_OPTION) { noButton = createNoButton( (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_NONDEFAULT && defaultButton!=NO_OPTION) || (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_DEFAULT && defaultButton==NO_OPTION )); } if(options==OK_OPTION || options==OK_CANCEL_OPTION) { okButton = createOKButton( (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_NONDEFAULT && defaultButton!=OK_OPTION) || (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_DEFAULT && defaultButton==OK_OPTION )); } if(options==SAVE_OPTION || options==SAVE_DONT_SAVE_CANCEL_OPTION) { saveButton = createSaveButton( (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_NONDEFAULT && defaultButton!=SAVE_OPTION) || (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_DEFAULT && defaultButton==SAVE_OPTION )); } if(options==YES_OPTION || options==YES_NO_OPTION || options==YES_NO_CANCEL_OPTION) { yesButton = createYesButton( (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_NONDEFAULT && defaultButton!=YES_OPTION) || (escapeKeyBehavior==ESCAPE_KEY_TRIGGERS_DEFAULT && defaultButton==YES_OPTION )); } if(options==CANCEL_OPTION) { dismissControls = new JButton[] { cancelButton }; } else if(options==DONT_SAVE_OPTION) { dismissControls = new JButton[] { dontSaveButton }; } else if(options==NO_OPTION) { dismissControls = new JButton[] { noButton }; } else if(options==OK_CANCEL_OPTION) { dismissControls = new JButton[] { okButton, cancelButton }; } else if(options==OK_OPTION) { dismissControls = new JButton[] { okButton }; } else if(options==SAVE_DONT_SAVE_CANCEL_OPTION) { dontSaveButton.putClientProperty(DialogFooter.PROPERTY_UNSAFE, Boolean.TRUE); if(JVM.isMac) { dismissControls = new JButton[] { saveButton, cancelButton, dontSaveButton }; } else { dismissControls = new JButton[] { saveButton, dontSaveButton, cancelButton }; } } else if(options==SAVE_OPTION) { dismissControls = new JButton[] { saveButton }; } else if(options==YES_NO_CANCEL_OPTION) { dismissControls = new JButton[] { yesButton, noButton, cancelButton }; } else if(options==YES_NO_OPTION) { dismissControls = new JButton[] { yesButton, noButton }; } else if(options==YES_OPTION) { dismissControls = new JButton[] { yesButton }; } else { throw new IllegalArgumentException("Unrecognized dialog type."); } JButton theDefaultButton = null; for(int a = 0; abutton.doClick(). */ public static class ClickAction extends AbstractAction { private static final long serialVersionUID = 1L; JButton button; public ClickAction(JButton button) { this.button = button; } public void actionPerformed(ActionEvent e) { button.doClick(); } } public static final boolean isMac = System.getProperty("os.name").toLowerCase().indexOf("mac")!=-1; public static final boolean isVista = System.getProperty("os.name").toLowerCase().indexOf("vista")!=-1; /** This client property is used to impose a meta-shortcut to click a button. * This should map to a Character. */ public static final String PROPERTY_META_SHORTCUT = "Dialog.meta.shortcut"; /** This client property is used to indicate a button is "unsafe". Apple * guidelines state that "unsafe" buttons (such as "discard changes") should * be several pixels away from "safe" buttons. */ public static final String PROPERTY_UNSAFE = "Dialog.Unsafe.Action"; /** This indicates whether the dismiss controls should be displayed in reverse * order. When you construct a DialogFooter, the dismiss controls should be listed * in order of priority (with the most preferred listed first, the least preferred last). * If this boolean is false, then those components will be listed in that order. If this is * true, then those components will be listed in the reverse order. *

    By default on Mac this is true, because Macs put the default button on the right * side of dialogs. On all other platforms this is false by default. *

    Window's guidelines * advise to, "Position the most important button -- typically the default command -- * as the first button in the set." */ public static boolean reverseButtonOrder = isMac; protected JComponent[] leftControls; protected JComponent[] dismissControls; protected JComponent lastSelectedComponent; protected boolean autoClose = false; protected JButton defaultButton = null; private final ActionListener innerActionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { lastSelectedComponent = (JComponent)e.getSource(); fireActionListeners(e); if(autoClose) closeDialogAndDisposeAction.actionPerformed(e); } }; /** Clones an array of JComponents */ private static JComponent[] copy(JComponent[] c) { JComponent[] newArray = new JComponent[c.length]; for(int a = 0; aDialogFooter. * * @param leftControls the controls on the left side of this dialog, such as a help component, or a "Reset" button. * @param dismissControls the controls on the right side of this dialog that should dismiss this dialog. Also * called "action" buttons. * @param autoClose whether the dismiss buttons should automatically close the containing window. * If this is false, then it is assumed someone else is taking care of closing/disposing the * containing dialog * @param defaultButton the optional button in dismissControls to make the default button in this dialog. * (May be null.) */ public DialogFooter(JComponent[] leftControls,JComponent[] dismissControls,boolean autoClose,JButton defaultButton) { super(new GridBagLayout()); this.autoClose = autoClose; //this may be common: if(leftControls==null) leftControls = new JComponent[] {}; //erg, this shouldn't be, but let's not throw an error because of it? if(dismissControls==null) dismissControls = new JComponent[] {}; this.leftControls = copy(leftControls); this.dismissControls = copy(dismissControls); this.defaultButton = defaultButton; if(leftControls==null) leftControls = new JComponent[] {}; if(dismissControls==null) dismissControls = new JComponent[] {}; GridBagConstraints c = new GridBagConstraints(); int buttonPadding; if(isMac) { buttonPadding = 12; } else if(isVista) { buttonPadding = 8; } else { buttonPadding = 6; } c.gridx = 0; c.gridy = 0; c.weightx = 0; c.weighty = 1; c.fill = GridBagConstraints.NONE; c.insets = new Insets(0,0,0,0); c.anchor = GridBagConstraints.CENTER; for(int a = 0; a(More specifically, this sets the preferredSize * of each button to the largest preferred size in the list of buttons. * * @param buttons an array of buttons. */ public static void normalizeButtons(JButton[] buttons) { int maxWidth = 0; int maxHeight = 0; for(int a = 0; aActionListener. * * @param l this listener will be notified when a dismissControl is activated. */ public void addActionListener(ActionListener l) { if(listeners==null) listeners = new Vector(); if(listeners.contains(l)) return; listeners.add(l); } /** Removes an ActionListener. */ public void removeActionListener(ActionListener l) { if(listeners==null) return; listeners.remove(l); } private void fireActionListeners(ActionEvent e) { if(listeners==null) return; for(int a = 0; aNote the components on the left side of this footer * (such as a "Help" button or a "Reset Preferences" button) * do NOT dismiss the dialog, and so this method has nothing * to do with those components. This only related to the components on the * right side of dialog. * @return the component last used to dismiss the dialog. */ public JComponent getLastSelectedComponent() { return lastSelectedComponent; } /** Finds a certain type of button, if it is available. * * @param buttonType of the options in this class (such as YES_OPTION or CANCEL_OPTION) * @return the button that maps to that option, or null if no such button was found. */ public JButton getButton(int buttonType) { for(int a = 0; alastSelectedComponent to null. *

    If this footer is recycled in different dialogs, then you may * need to nullify this value for getLastSelectedComponent() * to remain relevant. */ public void reset() { lastSelectedComponent = null; } /** Returns a copy of the dismissControls array used to construct this footer. */ public JComponent[] getDismissControls() { return copy(dismissControls); } /** Returns a copy of the leftControls array used to construct this footer. */ public JComponent[] getLeftControls() { return copy(leftControls); } /** This action takes the Window associated with the source of this event, * hides it, and then calls dispose() on it. *

    (This will not throw an exception if there is no parent window, * but it does nothing in that case...) */ public static Action closeDialogAndDisposeAction = new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { Component src = (Component)e.getSource(); Window w = SwingUtilities.getWindowAncestor(src); if(w==null) return; w.setVisible(false); w.dispose(); } }; } colorpicker-1.0.0/com/bric/swing/ColorPicker.java0000644000175000017500000010411411437472304021257 0ustar andrewandrew/* * @(#)ColorPicker.java * * $Date: 2010-01-03 08:01:13 -0600 (Sun, 03 Jan 2010) $ * * Copyright (c) 2009 by Jeremy Wood. * All rights reserved. * * The copyright of this software is owned by Jeremy Wood. * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * Jeremy Wood. For details see accompanying license terms. * * This software is probably, but not necessarily, discussed here: * http://javagraphics.blogspot.com/ * * And the latest version should be available here: * https://javagraphics.dev.java.net/ */ package com.bric.swing; import java.awt.Color; import java.awt.Dialog; import java.awt.Dimension; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ResourceBundle; import javax.swing.ButtonGroup; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JSlider; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import com.bric.plaf.ColorPickerSliderUI; /** This is a panel that offers a robust set of controls to pick a color. *

    This was originally intended to replace the JColorChooser. * To use this class to create a color choosing dialog, simply call: *
    ColorPicker.showDialog(frame, originalColor); *

    However this panel is also resizable, and it can exist in other contexts. * For example, you might try the following panel: *
    ColorPicker picker = new ColorPicker(false, false); *
    picker.setPreferredSize(new Dimension(200,160)); *
    picker.setMode(ColorPicker.HUE); *

    This will create a miniature color picker that still lets the user choose * from every available color, but it does not include all the buttons and * numeric controls on the right side of the panel. This might be ideal if you * are working with limited space, or non-power-users who don't need the * RGB values of a color. The main() method of this class demonstrates * possible ways you can customize a ColorPicker component. *

    To listen to color changes to this panel, you can add a PropertyChangeListener * listening for changes to the SELECTED_COLOR_PROPERTY. This will be triggered only * when the RGB value of the selected color changes. *

    To listen to opacity changes to this panel, use a PropertyChangeListener listening * for changes to the OPACITY_PROPERTY. * */ public class ColorPicker extends JPanel { private static final long serialVersionUID = 3L; /** The localized strings used in this (and related) panel(s). */ protected static ResourceBundle strings = ResourceBundle.getBundle("com.bric.swing.resources.ColorPicker"); /** This creates a modal dialog prompting the user to select a color. *

    This uses a generic dialog title: "Choose a Color", and does not include opacity. * * @param owner the dialog this new dialog belongs to. This must be a Frame or a Dialog. * Java 1.6 supports Windows here, but this package is designed/compiled to work in Java 1.4, * so an IllegalArgumentException will be thrown if this component is a Window. * @param originalColor the color the ColorPicker initially points to. * @return the Color the user chooses, or null if the user cancels the dialog. */ public static Color showDialog(Window owner,Color originalColor) { return showDialog(owner, null, originalColor, false ); } /** This creates a modal dialog prompting the user to select a color. *

    This uses a generic dialog title: "Choose a Color". * * @param owner the dialog this new dialog belongs to. This must be a Frame or a Dialog. * Java 1.6 supports Windows here, but this package is designed/compiled to work in Java 1.4, * so an IllegalArgumentException will be thrown if this component is a Window. * @param originalColor the color the ColorPicker initially points to. * @param includeOpacity whether to add a control for the opacity of the color. * @return the Color the user chooses, or null if the user cancels the dialog. */ public static Color showDialog(Window owner,Color originalColor,boolean includeOpacity) { return showDialog(owner, null, originalColor, includeOpacity ); } /** This creates a modal dialog prompting the user to select a color. * * @param owner the dialog this new dialog belongs to. This must be a Frame or a Dialog. * Java 1.6 supports Windows here, but this package is designed/compiled to work in Java 1.4, * so an IllegalArgumentException will be thrown if this component is a Window. * @param title the title for the dialog. * @param originalColor the color the ColorPicker initially points to. * @param includeOpacity whether to add a control for the opacity of the color. * @return the Color the user chooses, or null if the user cancels the dialog. */ public static Color showDialog(Window owner, String title,Color originalColor,boolean includeOpacity) { ColorPickerDialog d; if(owner instanceof Frame || owner==null) { d = new ColorPickerDialog( (Frame)owner, originalColor, includeOpacity); } else if(owner instanceof Dialog){ d = new ColorPickerDialog( (Dialog)owner, originalColor, includeOpacity); } else { throw new IllegalArgumentException("the owner ("+owner.getClass().getName()+") must be a java.awt.Frame or a java.awt.Dialog"); } d.setTitle(title == null ? strings.getObject("ColorPickerDialogTitle").toString() : title); d.pack(); d.setVisible(true); return d.getColor(); } /** PropertyChangeEvents will be triggered for this property when the selected color * changes. *

    (Events are only created when then RGB values of the color change. This means, for example, * that the change from HSB(0,0,0) to HSB(.4,0,0) will not generate events, because when the * brightness stays zero the RGB color remains (0,0,0). So although the hue moved around, the color * is still black, so no events are created.) * */ public static final String SELECTED_COLOR_PROPERTY = "selected color"; /** PropertyChangeEvents will be triggered for this property when setModeControlsVisible() * is called. */ public static final String MODE_CONTROLS_VISIBLE_PROPERTY = "mode controls visible"; /** PropertyChangeEvents will be triggered when the opacity value is * adjusted. */ public static final String OPACITY_PROPERTY = "opacity"; /** PropertyChangeEvents will be triggered when the mode changes. * (That is, when the wheel switches from HUE, SAT, BRI, RED, GREEN, or BLUE modes.) */ public static final String MODE_PROPERTY = "mode"; /** Used to indicate when we're in "hue mode". */ public static final int HUE = 0; /** Used to indicate when we're in "brightness mode". */ public static final int BRI = 1; /** Used to indicate when we're in "saturation mode". */ public static final int SAT = 2; /** Used to indicate when we're in "red mode". */ public static final int RED = 3; /** Used to indicate when we're in "green mode". */ public static final int GREEN = 4; /** Used to indicate when we're in "blue mode". */ public static final int BLUE = 5; /** The vertical slider */ private JSlider slider = new JSlider(JSlider.VERTICAL,0,100,0); private int currentRed = 0; private int currentGreen = 0; private int currentBlue = 0; ChangeListener changeListener = new ChangeListener() { public void stateChanged(ChangeEvent e) { Object src = e.getSource(); if(hue.contains(src) || sat.contains(src) || bri.contains(src)) { if(adjustingSpinners>0) return; setHSB( hue.getFloatValue()/360f, sat.getFloatValue()/100f, bri.getFloatValue()/100f ); } else if(red.contains(src) || green.contains(src) || blue.contains(src)) { if(adjustingSpinners>0) return; setRGB( red.getIntValue(), green.getIntValue(), blue.getIntValue() ); } else if(src==colorPanel) { if(adjustingColorPanel>0) return; int mode = getMode(); if(mode==HUE || mode==BRI || mode==SAT) { float[] hsb = colorPanel.getHSB(); setHSB(hsb[0],hsb[1],hsb[2]); } else { int[] rgb = colorPanel.getRGB(); setRGB(rgb[0],rgb[1],rgb[2]); } } else if(src==slider) { if(adjustingSlider>0) return; int v = slider.getValue(); Option option = getSelectedOption(); option.setValue(v); } else if(alpha.contains(src)) { if(adjustingOpacity>0) return; int v = alpha.getIntValue(); setOpacity( v ); } else if(src==opacitySlider) { if(adjustingOpacity>0) return; setOpacity( opacitySlider.getValue() ); } } }; ActionListener actionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if(src==hue.radioButton) { setMode(HUE); } else if(src==bri.radioButton) { setMode(BRI); } else if(src==sat.radioButton) { setMode(SAT); } else if(src==red.radioButton) { setMode(RED); } else if(src==green.radioButton) { setMode(GREEN); } else if(src==blue.radioButton) { setMode(BLUE); } } }; /** @return the currently selected Option */ private Option getSelectedOption() { int mode = getMode(); if(mode==HUE) { return hue; } else if(mode==SAT) { return sat; } else if(mode==BRI) { return bri; } else if(mode==RED) { return red; } else if(mode==GREEN) { return green; } else { return blue; } } /** This thread will wait a second or two before committing the text in * the hex TextField. This gives the user a chance to finish typing... * but if the user is just waiting for something to happen, this makes sure * after a second or two something happens. */ class HexUpdateThread extends Thread { long myStamp; String text; public HexUpdateThread(long stamp,String s) { myStamp = stamp; text = s; } public void run() { if(SwingUtilities.isEventDispatchThread()==false) { long WAIT = 1500; while(System.currentTimeMillis()-myStamp6) text = text.substring(0,6); while(text.length()<6) { text = text+"0"; } if(hexField.getText().equals(text)) return; int pos = hexField.getCaretPosition(); hexField.setText(text); hexField.setCaretPosition(pos); } } HexDocumentListener hexDocListener = new HexDocumentListener(); class HexDocumentListener implements DocumentListener { long lastTimeStamp; public void changedUpdate(DocumentEvent e) { lastTimeStamp = System.currentTimeMillis(); if(adjustingHexField>0) return; String s = hexField.getText(); s = stripToHex(s); if(s.length()==6) { //the user typed 6 digits: we can work with this: try { int i = Integer.parseInt(s,16); setRGB( ((i >> 16) & 0xff), ((i >> 8) & 0xff), ((i) & 0xff) ); return; } catch(NumberFormatException e2) { //this shouldn't happen, since we already stripped out non-hex characters. e2.printStackTrace(); } } Thread thread = new HexUpdateThread(lastTimeStamp,s); thread.start(); while(System.currentTimeMillis()-lastTimeStamp==0) { Thread.yield(); } } /** Strips a string down to only uppercase hex-supported characters. */ private String stripToHex(String s) { s = s.toUpperCase(); String s2 = ""; for(int a = 0; aColorPicker with all controls visible except opacity. */ public ColorPicker() { this(true,false); } /** Create a new ColorPicker. * * @param showExpertControls the labels/spinners/buttons on the right side of a * ColorPicker are optional. This boolean will control whether they * are shown or not. *

    It may be that your users will never need or want numeric control when * they choose their colors, so hiding this may simplify your interface. * @param includeOpacity whether the opacity controls will be shown */ public ColorPicker(boolean showExpertControls,boolean includeOpacity) { super(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); Insets normalInsets = new Insets(3,3,3,3); JPanel options = new JPanel(new GridBagLayout()); c.gridx = 0; c.gridy = 0; c.weightx = 1; c.weighty = 1; c.insets = normalInsets; ButtonGroup bg = new ButtonGroup(); //put them in order Option[] optionsArray = new Option[] { hue, sat, bri, red, green, blue }; for(int a = 0; aNote this lives inside the "expert controls", so if setExpertControlsVisible(false) * has been called, then calling this method makes no difference: the hex controls will be hidden. */ public void setHexControlsVisible(boolean b) { hexLabel.setVisible(b); hexField.setVisible(b); } /** This controls whether the preview swatch visible or not. *

    Note this lives inside the "expert controls", so if setExpertControlsVisible(false) * has been called, then calling this method makes no difference: the swatch will be hidden. */ public void setPreviewSwatchVisible(boolean b) { preview.setVisible(b); } /** The labels/spinners/buttons on the right side of a ColorPicker * are optional. This method will control whether they are shown or not. *

    It may be that your users will never need or want numeric control when * they choose their colors, so hiding this may simplify your interface. * * @param b whether to show or hide the expert controls. */ public void setExpertControlsVisible(boolean b) { expertControls.setVisible(b); } /** @return the current HSB coordinates of this ColorPicker. * Each value is between [0,1]. * */ public float[] getHSB() { return new float[] { hue.getFloatValue()/360f, sat.getFloatValue()/100f, bri.getFloatValue()/100f }; } /** @return the current RGB coordinates of this ColorPicker. * Each value is between [0,255]. * */ public int[] getRGB() { return new int[] { currentRed, currentGreen, currentBlue }; } /** Returns the currently selected opacity (a float between 0 and 1). * * @return the currently selected opacity (a float between 0 and 1). */ public float getOpacity() { return ((float)opacitySlider.getValue())/255f; } private int lastOpacity = 255; /** Sets the currently selected opacity. * * @param v an int between 0 and 255. */ public void setOpacity(int v) { if(v<0 || v>255) throw new IllegalArgumentException("The opacity ("+v+") must be between 0 and 255."); adjustingOpacity++; try { opacitySlider.setValue( v ); alpha.spinner.setValue( new Integer(v) ); if(lastOpacity!=v) { firePropertyChange(OPACITY_PROPERTY,new Integer(lastOpacity),new Integer(v)); Color c = preview.getForeground(); preview.setForeground(new Color(c.getRed(), c.getGreen(), c.getBlue(), v)); } lastOpacity = v; } finally { adjustingOpacity--; } } /** Sets the mode of this ColorPicker. * This is especially useful if this picker is in non-expert mode, so * the radio buttons are not visible for the user to directly select. * * @param mode must be HUE, SAT, BRI, RED, GREEN or BLUE. */ public void setMode(int mode) { if(!(mode==HUE || mode==SAT || mode==BRI || mode==RED || mode==GREEN || mode==BLUE)) throw new IllegalArgumentException("mode must be HUE, SAT, BRI, REd, GREEN, or BLUE"); putClientProperty(MODE_PROPERTY,new Integer(mode)); hue.radioButton.setSelected(mode==HUE); sat.radioButton.setSelected(mode==SAT); bri.radioButton.setSelected(mode==BRI); red.radioButton.setSelected(mode==RED); green.radioButton.setSelected(mode==GREEN); blue.radioButton.setSelected(mode==BLUE); colorPanel.setMode(mode); adjustingSlider++; try { slider.setValue(0); Option option = getSelectedOption(); slider.setInverted(mode==HUE); int max = option.getMaximum(); slider.setMaximum(max); slider.setValue( option.getIntValue() ); slider.repaint(); if(mode==HUE || mode==SAT || mode==BRI) { setHSB( hue.getFloatValue()/360f, sat.getFloatValue()/100f, bri.getFloatValue()/100f ); } else { setRGB( red.getIntValue(), green.getIntValue(), blue.getIntValue() ); } } finally { adjustingSlider--; } } /** This controls whether the radio buttons that adjust the mode are visible. *

    (These buttons appear next to the spinners in the expert controls.) *

    Note these live inside the "expert controls", so if setExpertControlsVisible(false) * has been called, then these will never be visible. * * @param b */ public void setModeControlsVisible(boolean b) { hue.radioButton.setVisible(b && hue.isVisible()); sat.radioButton.setVisible(b && sat.isVisible()); bri.radioButton.setVisible(b && bri.isVisible()); red.radioButton.setVisible(b && red.isVisible()); green.radioButton.setVisible(b && green.isVisible()); blue.radioButton.setVisible(b && blue.isVisible()); putClientProperty(MODE_CONTROLS_VISIBLE_PROPERTY,new Boolean(b)); } /** @return the current mode of this ColorPicker. *
    This will return HUE, SAT, BRI, * RED, GREEN, or BLUE. *

    The default mode is BRI, because that provides the most * aesthetic/recognizable color wheel. */ public int getMode() { Integer i = (Integer)getClientProperty(MODE_PROPERTY); if(i==null) return -1; return i.intValue(); } /** Sets the current color of this ColorPicker. * This method simply calls setRGB() and setOpacity(). * @param c the new color to use. */ public void setColor(Color c) { setRGB(c.getRed(),c.getGreen(),c.getBlue()); setOpacity(c.getAlpha()); } /** Sets the current color of this ColorPicker * * @param r the red value. Must be between [0,255]. * @param g the green value. Must be between [0,255]. * @param b the blue value. Must be between [0,255]. */ public void setRGB(int r,int g,int b) { if(r<0 || r>255) throw new IllegalArgumentException("The red value ("+r+") must be between [0,255]."); if(g<0 || g>255) throw new IllegalArgumentException("The green value ("+g+") must be between [0,255]."); if(b<0 || b>255) throw new IllegalArgumentException("The blue value ("+b+") must be between [0,255]."); Color lastColor = getColor(); boolean updateRGBSpinners = adjustingSpinners==0; adjustingSpinners++; adjustingColorPanel++; int alpha = this.alpha.getIntValue(); try { if(updateRGBSpinners) { red.setValue(r); green.setValue(g); blue.setValue(b); } preview.setForeground(new Color(r,g,b, alpha)); float[] hsb = new float[3]; Color.RGBtoHSB(r, g, b, hsb); hue.setValue( (int)(hsb[0]*360f+.49f)); sat.setValue( (int)(hsb[1]*100f+.49f)); bri.setValue( (int)(hsb[2]*100f+.49f)); colorPanel.setRGB(r, g, b); updateHexField(); updateSlider(); } finally { adjustingSpinners--; adjustingColorPanel--; } currentRed = r; currentGreen = g; currentBlue = b; Color newColor = getColor(); if(lastColor.equals(newColor)==false) firePropertyChange(SELECTED_COLOR_PROPERTY,lastColor,newColor); } /** @return the current Color this ColorPicker has selected. *

    This is equivalent to: *
    int[] i = getRGB(); *
    return new Color(i[0], i[1], i[2], opacitySlider.getValue()); */ public Color getColor() { int[] i = getRGB(); return new Color(i[0], i[1], i[2], opacitySlider.getValue()); } private void updateSlider() { adjustingSlider++; try { int mode = getMode(); if(mode==HUE) { slider.setValue( hue.getIntValue() ); } else if(mode==SAT) { slider.setValue( sat.getIntValue() ); } else if(mode==BRI) { slider.setValue( bri.getIntValue() ); } else if(mode==RED) { slider.setValue( red.getIntValue() ); } else if(mode==GREEN) { slider.setValue( green.getIntValue() ); } else if(mode==BLUE) { slider.setValue( blue.getIntValue() ); } } finally { adjustingSlider--; } slider.repaint(); } /** This returns the panel with several rows of spinner controls. *

    Note you can also call methods such as setRGBControlsVisible() to adjust * which controls are showing. *

    (This returns the panel this ColorPicker uses, so if you put it in * another container, it will be removed from this ColorPicker.) * @return the panel with several rows of spinner controls. */ public JPanel getExpertControls() { return expertControls; } /** This shows or hides the RGB spinner controls. *

    Note these live inside the "expert controls", so if setExpertControlsVisible(false) * has been called, then calling this method makes no difference: the RGB controls will be hidden. * * @param b whether the controls should be visible or not. */ public void setRGBControlsVisible(boolean b) { red.setVisible(b); green.setVisible(b); blue.setVisible(b); } /** This shows or hides the HSB spinner controls. *

    Note these live inside the "expert controls", so if setExpertControlsVisible(false) * has been called, then calling this method makes no difference: the HSB controls will be hidden. * * @param b whether the controls should be visible or not. */ public void setHSBControlsVisible(boolean b) { hue.setVisible(b); sat.setVisible(b); bri.setVisible(b); } /** This shows or hides the alpha controls. *

    Note the alpha spinner live inside the "expert controls", so if setExpertControlsVisible(false) * has been called, then this method does not affect that spinner. * However, the opacity slider is not affected by the visibility of the export controls. * @param b */ public void setOpacityVisible(boolean b) { opacityLabel.setVisible(b); opacitySlider.setVisible(b); alpha.label.setVisible(b); alpha.spinner.setVisible(b); } /** @return the ColorPickerPanel this ColorPicker displays. */ public ColorPickerPanel getColorPanel() { return colorPanel; } /** Sets the current color of this ColorPicker * * @param h the hue value. * @param s the saturation value. Must be between [0,1]. * @param b the blue value. Must be between [0,1]. */ public void setHSB(float h, float s, float b) { if(Float.isInfinite(h) || Float.isNaN(h)) throw new IllegalArgumentException("The hue value ("+h+") is not a valid number."); //hue is cyclic, so it can be any value: while(h<0) h++; while(h>1) h--; if(s<0 || s>1) throw new IllegalArgumentException("The saturation value ("+s+") must be between [0,1]"); if(b<0 || b>1) throw new IllegalArgumentException("The brightness value ("+b+") must be between [0,1]"); Color lastColor = getColor(); boolean updateHSBSpinners = adjustingSpinners==0; adjustingSpinners++; adjustingColorPanel++; try { if(updateHSBSpinners) { hue.setValue( (int)(h*360f+.49f)); sat.setValue( (int)(s*100f+.49f)); bri.setValue( (int)(b*100f+.49f)); } Color c = new Color(Color.HSBtoRGB(h, s, b)); int alpha = this.alpha.getIntValue(); c = new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha); preview.setForeground(c); currentRed = c.getRed(); currentGreen = c.getGreen(); currentBlue = c.getBlue(); red.setValue(currentRed); green.setValue(currentGreen); blue.setValue(currentBlue); colorPanel.setHSB(h, s, b); updateHexField(); updateSlider(); slider.repaint(); } finally { adjustingSpinners--; adjustingColorPanel--; } Color newColor = getColor(); if(lastColor.equals(newColor)==false) firePropertyChange(SELECTED_COLOR_PROPERTY,lastColor,newColor); } private void updateHexField() { adjustingHexField++; try { int r = red.getIntValue(); int g = green.getIntValue(); int b = blue.getIntValue(); int i = (r << 16) + (g << 8) +b; String s = Integer.toHexString(i).toUpperCase(); while(s.length()<6) s = "0"+s; if(hexField.getText().equalsIgnoreCase(s)==false) hexField.setText(s); } finally { adjustingHexField--; } } class Option { JRadioButton radioButton = new JRadioButton(); JSpinner spinner; JSlider slider; JLabel label; public Option(String text,int max) { spinner = new JSpinner(new SpinnerNumberModel(0,0,max,5)); spinner.addChangeListener(changeListener); /*this tries out Tim Boudreaux's new slider UI. * It's a good UI, but I think for the ColorPicker * the numeric controls are more useful. * That is: users who want click-and-drag control to choose * their colors don't need any of these Option objects * at all; only power users who may have specific RGB * values in mind will use these controls: and when they do * limiting them to a slider is unnecessary. * That's my current position... of course it may * not be true in the real world... :) */ //slider = new JSlider(0,max); //slider.addChangeListener(changeListener); //slider.setUI(new org.netbeans.paint.api.components.PopupSliderUI()); label = new JLabel(text); radioButton.addActionListener(actionListener); } public void setValue(int i) { if(slider!=null) { slider.setValue(i); } if(spinner!=null) { spinner.setValue(new Integer(i)); } } public int getMaximum() { if(slider!=null) return slider.getMaximum(); return ((Number) ((SpinnerNumberModel)spinner.getModel()).getMaximum() ).intValue(); } public boolean contains(Object src) { return (src==slider || src==spinner || src==radioButton || src==label); } public float getFloatValue() { return getIntValue(); } public int getIntValue() { if(slider!=null) return slider.getValue(); return ((Number)spinner.getValue()).intValue(); } public boolean isVisible() { return label.isVisible(); } public void setVisible(boolean b) { boolean radioButtonsAllowed = true; Boolean z = (Boolean)getClientProperty(MODE_CONTROLS_VISIBLE_PROPERTY); if(z!=null) radioButtonsAllowed = z.booleanValue(); radioButton.setVisible(b && radioButtonsAllowed); if(slider!=null) slider.setVisible(b); if(spinner!=null) spinner.setVisible(b); label.setVisible(b); } } } colorpicker-1.0.0/com/bric/util/0000755000175000017500000000000011452722626016027 5ustar andrewandrewcolorpicker-1.0.0/com/bric/util/JVM.java0000644000175000017500000001015711437472304017330 0ustar andrewandrew/* * @(#)JVM.java * * $Date: 2010-01-26 10:38:02 -0600 (Tue, 26 Jan 2010) $ * * Copyright (c) 2009 by Jeremy Wood. * All rights reserved. * * The copyright of this software is owned by Jeremy Wood. * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * Jeremy Wood. For details see accompanying license terms. * * This software is probably, but not necessarily, discussed here: * http://javagraphics.blogspot.com/ * * And the latest version should be available here: * https://javagraphics.dev.java.net/ */ package com.bric.util; import java.security.AccessControlException; /** Static methods relating to the JVM environment. *

    Instead of burying a constant like "isQuartz" in its most * relevant class (such as OptimizedGraphics2D), it should be * stored here so if other classes need to access it they don't * necessary have to */ public class JVM { /** Prints basic information about this session's JVM: * the OS name & version, the Java version, and (on Mac) whether Quartz is being used. */ public static void printProfile() { System.out.println(getProfile()); } /** Gets basic information about this session's JVM: * the OS name & version, the Java version, and (on Mac) whether Quartz is being used. */ public static String getProfile() { StringBuffer sb = new StringBuffer(); sb.append("OS = "+System.getProperty("os.name")+" ("+System.getProperty("os.version")+"), "+System.getProperty("os.arch")+"\n"); sb.append("Java Version = "+System.getProperty("java.version")+"\n"); if(JVM.isMac) { sb.append("apple.awt.graphics.UseQuartz = "+usingQuartz); } return sb.toString(); } /** The major Java version being used (1.4, 1.5, 1.6, etc.), or * -1 if this value couldn't be correctly determined. */ public static final float javaVersion = JVM.getMajorJavaVersion(true); /** Whether this session is on a Mac. */ public static final boolean isMac = (System.getProperty("os.name").toLowerCase().indexOf("mac")!=-1); /** Whether this session is on Windows. */ public static final boolean isWindows = (System.getProperty("os.name").toLowerCase().indexOf("windows")!=-1); /** Whether this session is on Vista. */ public static final boolean isVista = (System.getProperty("os.name").toLowerCase().indexOf("vista")!=-1); /** If on a Mac: whether Quartz is the rendering pipeline. */ public static final boolean usingQuartz = isMac && ((javaVersion>0 && javaVersion<1.4f) || (System.getProperty("apple.awt.graphics.UseQuartz")!=null && System.getProperty("apple.awt.graphics.UseQuartz").toString().equals("true"))); /** This converts the system property "java.version" to a float value. * This drops rightmost digits until a legitimate float can be parsed. *
    For example, this converts "1.6.0_05" to "1.6". *
    This value is cached as the system property "java.major.version". Although * technically this value is a String, it will always be parseable as a float. * @throws AccessControlException this may be thrown in unsigned applets! Beware! */ public static float getMajorJavaVersion() throws AccessControlException { String majorVersion = System.getProperty("java.major.version"); if(majorVersion==null) { String s = System.getProperty("java.version"); float f = -1; int i = s.length(); while(f<0 && i>0) { try { f = Float.parseFloat(s.substring(0,i)); } catch(Exception e) {} i--; } majorVersion = Float.toString(f); System.setProperty("java.major.version",majorVersion); } return Float.parseFloat(majorVersion); } /** * * @param catchSecurityException if true and an exception occurs, * then -1 is returned. * @return the major java version, or -1 if this can't be determined/ */ public static float getMajorJavaVersion(boolean catchSecurityException) { try { return getMajorJavaVersion(); } catch(RuntimeException t) { if(catchSecurityException) { System.err.println("this exception was ignored without incident, but it means we can't determine the major java version:"); t.printStackTrace(); return -1; } throw t; } } } colorpicker-1.0.0/com/bric/plaf/0000755000175000017500000000000011452722626015774 5ustar andrewandrewcolorpicker-1.0.0/com/bric/plaf/ColorPickerSliderUI.java0000644000175000017500000001411611437472304022455 0ustar andrewandrew/* * @(#)ColorPickerSliderUI.java * * $Date: 2010-03-19 19:18:15 -0500 (Fri, 19 Mar 2010) $ * * Copyright (c) 2009 by Jeremy Wood. * All rights reserved. * * The copyright of this software is owned by Jeremy Wood. * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * Jeremy Wood. For details see accompanying license terms. * * This software is probably, but not necessarily, discussed here: * http://javagraphics.blogspot.com/ * * And the latest version should be available here: * https://javagraphics.dev.java.net/ */ package com.bric.plaf; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.TexturePaint; import java.awt.Toolkit; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import javax.swing.JSlider; import javax.swing.event.MouseInputAdapter; import javax.swing.plaf.basic.BasicSliderUI; import com.bric.swing.ColorPicker; import com.bric.swing.ColorPickerPanel; /** This is a SliderUI designed specifically for the * ColorPicker. * */ public class ColorPickerSliderUI extends BasicSliderUI { ColorPicker colorPicker; /** Half of the height of the arrow */ int ARROW_HALF = 8; int[] intArray = new int[ Toolkit.getDefaultToolkit().getScreenSize().height ]; BufferedImage bi = new BufferedImage(1,intArray.length,BufferedImage.TYPE_INT_RGB); int lastMode = -1; public ColorPickerSliderUI(JSlider b,ColorPicker cp) { super(b); colorPicker = cp; cp.getColorPanel().addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { ColorPickerSliderUI.this.calculateGeometry(); slider.repaint(); } }); } public void paintThumb(Graphics g) { int y = thumbRect.y+thumbRect.height/2; Polygon polygon = new Polygon(); polygon.addPoint(0,y-ARROW_HALF); polygon.addPoint(ARROW_HALF,y); polygon.addPoint(0,y+ARROW_HALF); Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(Color.black); g2.fill(polygon); g2.setColor(Color.white); g2.setStroke(new BasicStroke(1)); g2.draw(polygon); } protected void calculateThumbSize() { super.calculateThumbSize(); thumbRect.height+=4; thumbRect.y-=2; } protected void calculateTrackRect() { super.calculateTrackRect(); ColorPickerPanel cp = colorPicker.getColorPanel(); int size = Math.min(ColorPickerPanel.MAX_SIZE, Math.min(cp.getWidth(), cp.getHeight())); int max = slider.getHeight()-ARROW_HALF*2-2; if(size>max) { size = max; } trackRect.y = slider.getHeight()/2-size/2; trackRect.height = size; } public synchronized void paintTrack(Graphics g) { int mode = colorPicker.getMode(); if(mode==ColorPicker.HUE || mode==ColorPicker.BRI || mode==ColorPicker.SAT) { float[] hsb = colorPicker.getHSB(); if(mode==ColorPicker.HUE) { for(int y = 0; yUIManager.put("focusRing",customColor); */ public static Color getFocusRingColor() { Object obj = UIManager.getColor("Focus.color"); if(obj instanceof Color) return (Color)obj; obj = UIManager.getColor("focusRing"); if(obj instanceof Color) return (Color)obj; return new Color(64,113,167); } /** Paints 3 different strokes around a shape to indicate focus. * The widest stroke is the most transparent, so this achieves a nice * "glow" effect. *

    The catch is that you have to render this underneath the shape, * and the shape should be filled completely. * * @param g the graphics to paint to * @param shape the shape to outline * @param pixelSize the number of pixels the outline should cover. */ public static void paintFocus(Graphics2D g,Shape shape,int pixelSize) { Color focusColor = getFocusRingColor(); Color[] focusArray = new Color[] { new Color(focusColor.getRed(), focusColor.getGreen(), focusColor.getBlue(),235), new Color(focusColor.getRed(), focusColor.getGreen(), focusColor.getBlue(),130), new Color(focusColor.getRed(), focusColor.getGreen(), focusColor.getBlue(),80) }; if(JVM.usingQuartz) { g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); } else { g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); } g.setStroke(new BasicStroke(2*pixelSize+1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); g.setColor(focusArray[2]); g.draw(shape); if(2*pixelSize+1>0) { g.setStroke(new BasicStroke(2*pixelSize-2+1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); g.setColor(focusArray[1]); g.draw(shape); } if(2*pixelSize-4+1>0) { g.setStroke(new BasicStroke(2*pixelSize-4+1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); g.setColor(focusArray[0]); g.draw(shape); } } /** Uses translucent shades of white and black to draw highlights * and shadows around a rectangle, and then frames the rectangle * with a shade of gray (120). *

    This should be called to add a finishing touch on top of * existing graphics. * @param g the graphics to paint to. * @param r the rectangle to paint. */ public static void drawBevel(Graphics2D g,Rectangle r) { g.setStroke(new BasicStroke(1)); drawColors(blacks,g, r.x, r.y+r.height, r.x+r.width, r.y+r.height, SwingConstants.SOUTH); drawColors(blacks,g, r.x+r.width, r.y, r.x+r.width, r.y+r.height, SwingConstants.EAST); drawColors(whites,g, r.x, r.y, r.x+r.width, r.y, SwingConstants.NORTH); drawColors(whites,g, r.x, r.y, r.x, r.y+r.height, SwingConstants.WEST); g.setColor(new Color(120, 120, 120)); g.drawRect(r.x, r.y, r.width, r.height); } private static void drawColors(Color[] colors,Graphics g,int x1,int y1,int x2,int y2,int direction) { for(int a = 0; a=positions[b-1] && fThis scans for the first available component whose * isFocusable() method returns true. * If no such component is found: nothing happens. */ public class FocusArrowListener extends KeyAdapter { public void keyPressed(KeyEvent e) { int code = e.getKeyCode(); int dx = 0; int dy = 0; if(code==KeyEvent.VK_LEFT) { dx = -1; } else if(code==KeyEvent.VK_UP) { dy = -1; } else if(code==KeyEvent.VK_RIGHT) { dx = 1; } else if(code==KeyEvent.VK_DOWN) { dy = 1; } if( (dx==0 && dy==0)==false && shiftFocus(dx,dy,(Component)e.getSource())) e.consume(); } /** Shifts the focus in a certain direction. * * @param dx the amount to increment x. * @param dy the amount to increment y. * @param src the source to traverse from. * @return true if another component requested the focus * as a result of this method. This may return false if * no suitable component was found to shift focus to. * (If you press the right arrow key on the right-most * component, for example.) */ public static boolean shiftFocus(int dx,int dy,Component src) { if(dx==0 && dy==0) //this would result in an infinite loop throw new IllegalArgumentException("dx ("+dx+") and ("+dy+") cannot both be zero"); Set focusableComponents = getFocusableComponents(src); int x = src.getWidth()/2; int y = src.getHeight()/2; Window window = SwingUtilities.getWindowAncestor(src); if(window==null) return false; Point p = SwingUtilities.convertPoint(src, x, y, window); Component comp = null; int windowWidth = window.getWidth(); int windowHeight = window.getHeight(); while(p.x>0 && p.x0 && p.yMy first implementation involved of this concept * simply involved asking JCompnonents if they were * focusable, but in the FilledButtonTest this * resulted in shifting focus to the ContentPane. Although * it is technically focusable: if I used the tab key * I did not get this result. So I studied * the inner workings for Component.transferFocus() * and ended up with a method that involved * calls to getFocusCycleRootAncestor(), * and getFocusTraversalPolicy(). *

    (Also credit goes to Werner for originally tipping me off * towards looking at FocusTraversalPolicies.) * @param currentFocusOwner the current focus owner. * @return all the JComponents that can receive the focus. */ public static Set getFocusableComponents(Component currentFocusOwner) { HashSet set = new HashSet(); set.add(currentFocusOwner); Container rootAncestor = currentFocusOwner.getFocusCycleRootAncestor(); Component comp = currentFocusOwner; while (rootAncestor != null && !(rootAncestor.isShowing() && rootAncestor.isFocusable() && rootAncestor.isEnabled())) { comp = rootAncestor; rootAncestor = comp.getFocusCycleRootAncestor(); } if (rootAncestor != null) { FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); Component toFocus = policy.getComponentAfter(rootAncestor, comp); final Component startingPoint = currentFocusOwner; while(toFocus!=null && set.contains(toFocus)==false) { set.add(toFocus); toFocus = policy.getComponentAfter(rootAncestor, toFocus); } toFocus = policy.getComponentBefore(rootAncestor, comp); while(toFocus!=null && set.contains(toFocus)==false) { set.add(toFocus); toFocus = policy.getComponentBefore(rootAncestor, toFocus); } } return set; } } colorpicker-1.0.0/info.txt0000644000175000017500000000037011437472304015047 0ustar andrewandrewThis jar was compiled to include the following classes: com/bric/swing/ColorPickerDemo To recreate/update this jar, run com.bric.jar.JarWriterApp and select these classes. You can click the "Load Jar" button to automatically select these classes.