All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pushingpixels.substance.internal.contrib.xoetrope.editor.color.ColorWheelPanel Maven / Gradle / Ivy

There is a newer version: 7.3
Show newest version
package org.pushingpixels.substance.internal.contrib.xoetrope.editor.color;

import java.awt.*;
import java.awt.event.*;
import java.awt.font.TextAttribute;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.text.AttributedString;
import java.util.*;

import javax.swing.*;
import javax.swing.colorchooser.AbstractColorChooserPanel;
import javax.swing.event.*;

/**
 * A color wheel showing a Red, Yellow, Blue color model traditionally used by
 * graphic artists. $Revision: 2254 $
 */
public class ColorWheelPanel extends AbstractColorChooserPanel implements
		ActionListener, MouseListener, MouseMotionListener, MouseWheelListener,
		ChangeListener {
	public static final int MONOCHROMATIC_SCHEME = 0;
	public static final int CONTRASTING_SCHEME = 1;
	public static final int SOFT_CONTRAST_SCHEME = 2;
	public static final int DOUBLE_CONTRAST_SCHEME = 3;
	public static final int ANALOGIC_SCHEME = 4;

	public static final int CTRL_ADJUST = 0;
	public static final int ALWAYS_ADJUST = 1;
	public static final int NEVER_ADJUST = 2;

	protected JTextField hueEdit, satEdit, brightEdit, baseColorEdit;
	protected BufferedImage pickerImage;
	protected ColorWheel imagePicker;
	protected JPanel fixedPanel;
	protected JButton resetBtn;
	protected JSlider brightnessSlider, saturationSlider;
	protected JLabel baseColorLabel;
	protected Ellipse2D innerCircle, outerCircle, borderCircle;
	protected JCheckBox useWebColors, decimalRGB;
	protected Font font9pt;

	protected ModelColor chooserColor;
	protected ModelColor[] selectedIttenColours;

	private float values[] = new float[3];
	private double h, s, b;

	private int colorScheme = 0;

	private boolean busy = false;
	private boolean displayScheme = false;
	private boolean hasChooser = false;

	private ArrayList changeListeners;
	private static double[] arcDelta = { -7.5, -7.5, -7.5, -7.5, -7.5, -1.0,
			4.0, 7.5 };

	private double ringThickness;
	private GeneralPath[] paths;
	private static ResourceBundle labelBundle;

	// Rollover related variables
	private GeneralPath rolloverPath, selectedPath;
	private boolean showRollovers;
	private Color rolloverColor, selectedColor;
	private Color systemColor;

	private String fontFamily;

	private int adjustWheel;
	private boolean adjustRollover;
	private boolean ctrlKeyDown;
	private double saturationMultipler, brightnessMultipler;

	/**
	 * Creates a new instance of ColorWheelPanel
	 */
	public ColorWheelPanel() {
		saturationMultipler = brightnessMultipler = 1.0;
		changeListeners = new ArrayList();
		adjustWheel = CTRL_ADJUST;
		adjustRollover = true;
		ctrlKeyDown = false;

		font9pt = UIManager.getFont("ColorChooser.smallFont");
		if (font9pt == null)
			font9pt = new Font("Arial", 0, 9);

		fontFamily = font9pt.getFamily();

		showRollovers = true;
		innerCircle = new Ellipse2D.Double(96, 96, 36, 36);
		outerCircle = new Ellipse2D.Double(6, 6, 214, 214);
		borderCircle = new Ellipse2D.Double(0, 0, 227, 227);

		fixedPanel = new JPanel();
		fixedPanel.setLayout(null);
		fixedPanel.setOpaque(false);
		// fixedPanel.setBackground( Color.white );
		fixedPanel.setBounds(0, 0, 255, 328);
		fixedPanel.setPreferredSize(new Dimension(255, 328));

		setLayout(new LayoutManager() {
			@Override
            public void addLayoutComponent(String name, Component comp) {
			}

			@Override
            public void removeLayoutComponent(Component comp) {
			}

			@Override
            public void layoutContainer(Container parent) {
				Dimension fpp = fixedPanel.getPreferredSize();
				int dx = (parent.getWidth() - fpp.width) / 2;
				int dy = (parent.getHeight() - fpp.height) / 2;
				fixedPanel.setBounds(dx, dy, fpp.width, fpp.height);
			}

			@Override
            public Dimension minimumLayoutSize(Container parent) {
				return preferredLayoutSize(parent);
			}

			@Override
            public Dimension preferredLayoutSize(Container parent) {
				return fixedPanel.getPreferredSize();
			}

		});
		imagePicker = new ColorWheel();
		imagePicker.setBounds(0, 0, 228, 228);
		imagePicker.addMouseListener(this);
		imagePicker.addMouseMotionListener(this);
		imagePicker.setOpaque(false);
		imagePicker.addMouseWheelListener(this);
		fixedPanel.add(imagePicker);

		brightnessSlider = new JSlider(JSlider.VERTICAL);
		brightnessSlider.setBounds(230, 0, 25, 108);
		brightnessSlider.setMinimum(0);
		brightnessSlider.setMaximum(100);
		brightnessSlider.setValue(100);
		brightnessSlider.setOpaque(false);
		// brightnessSlider.setBackground( Color.white );
		brightnessSlider.setPaintLabels(true);
		brightnessSlider.addChangeListener(this);
		brightnessSlider.addMouseWheelListener(this);
		brightnessSlider.addMouseMotionListener(this);
		brightnessSlider.setToolTipText(getLabel("Xoetrope.ctrlDrag",
				"CTRL+drag to adjust the color wheel"));
		fixedPanel.add(brightnessSlider);

		resetBtn = new JButton();
		resetBtn.setBounds(237, 109, 10, 10);
		resetBtn.setBackground(getBackground());
		resetBtn.addActionListener(this);
		resetBtn.setToolTipText(getLabel("Xoetrope.reset",
				"Reset the color wheel sauturation and brightness"));
		fixedPanel.add(resetBtn);

		saturationSlider = new JSlider(JSlider.VERTICAL);
		saturationSlider.setBounds(230, 120, 25, 110);
		saturationSlider.setMinimum(0);
		saturationSlider.setMaximum(100);
		saturationSlider.setValue(100);
		saturationSlider.setOpaque(false);
		// saturationSlider.setBackground( Color.white );
		saturationSlider.setInverted(true);
		saturationSlider.setPaintLabels(true);
		saturationSlider.addChangeListener(this);
		saturationSlider.addMouseWheelListener(this);
		saturationSlider.addMouseMotionListener(this);
		saturationSlider.setToolTipText(getLabel("Xoetrope.ctrlDrag",
				"CTRL+drag to adjust the color wheel"));
		fixedPanel.add(saturationSlider);

		useWebColors = new JCheckBox(getLabel("Xoetrope.webSafeColors",
				"Use web safe colors"));
		useWebColors.setBounds(8, 248, 160, 18);
		useWebColors.addActionListener(this);
		useWebColors.setOpaque(false);
		useWebColors.setFont(font9pt);
		fixedPanel.add(useWebColors);

		decimalRGB = new JCheckBox(getLabel("Xoetrope.decimalRGB",
				"Decimal RGB"));
		decimalRGB.setBounds(173, 248, 88, 18);
		decimalRGB.addActionListener(this);
		decimalRGB.setOpaque(false);
		decimalRGB.setFont(font9pt);
		fixedPanel.add(decimalRGB);

		baseColorLabel = new JLabel();
		baseColorLabel.setBounds(10, 268, 160, 18);
		baseColorLabel.setBackground(Color.red);
		baseColorLabel.setOpaque(true);
		baseColorLabel.setToolTipText(getLabel("Xoetrope.systemColorsTooltip",
				"Right click for system colours"));
		fixedPanel.add(baseColorLabel);
		baseColorLabel.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent me) {
				showSystemColorList(me.getPoint());
			}
		});

		baseColorEdit = new JTextField();
		baseColorEdit.setBounds(180, 268, 75, 18);
		baseColorEdit.setOpaque(true);
		fixedPanel.add(baseColorEdit);
		baseColorEdit.addActionListener(this);

		hueEdit = new JTextField();
		hueEdit.setBounds(10, 288, 75, 20);
		fixedPanel.add(hueEdit);
		hueEdit.setText("0");
		hueEdit.getDocument().addDocumentListener(
				new ColorDocumentListener(hueEdit));

		JLabel hueLabel = new JLabel(getLabel("Xoetrope.hue", "Hue")
				+ " \u00B0");
		hueLabel.setBounds(10, 308, 75, 20);
		hueLabel.setFont(font9pt);
		fixedPanel.add(hueLabel);

		satEdit = new JTextField();
		satEdit.setBounds(95, 288, 75, 20);
		fixedPanel.add(satEdit);
		satEdit.setText("0");
		satEdit.getDocument().addDocumentListener(
				new ColorDocumentListener(satEdit));

		JLabel satLabel = new JLabel(getLabel("Xoetrope.saturation",
				"Saturation")
				+ " %");
		satLabel.setBounds(95, 308, 75, 20);
		satLabel.setFont(font9pt);
		fixedPanel.add(satLabel);

		brightEdit = new JTextField();
		brightEdit.setBounds(180, 288, 75, 20);
		fixedPanel.add(brightEdit);
		brightEdit.setText("0");
		brightEdit.getDocument().addDocumentListener(
				new ColorDocumentListener(brightEdit));

		JLabel brightLabel = new JLabel(getLabel("Xoetrope.brightness",
				"Brightness")
				+ " %");
		brightLabel.setBounds(180, 308, 75, 20);
		brightLabel.setFont(font9pt);
		fixedPanel.add(brightLabel);

		add(fixedPanel);
	}

	/**
	 * Set the reference to the selected colours for the colour scheme
	 * 
	 * @param clrs
	 *            the colors
	 */
	public void setSelectedColors(ModelColor[] clrs) {
		selectedIttenColours = clrs;
	}

	/**
	 * Add a listener for changes in the selected color
	 * 
	 * @param l
	 *            the change listener to add
	 */
	public void addChangeListener(ChangeListener l) {
		changeListeners.add(l);
	}

	/**
	 * Remove a change listener
	 * 
	 * @param l
	 *            the change listener to remove
	 */
	public void removeChangeListener(ChangeListener l) {
		changeListeners.remove(l);
	}

	/**
	 * Has the user selected the use decimal rgb checkbox?
	 * 
	 * @return true if decimal rgb values are to be shown
	 */
	public boolean useDecimalRGB() {
		return decimalRGB.isSelected();
	}

	/**
	 * Has the user selected the use web safe colors checkbox?
	 * 
	 * @return true if only web safe colors are to be shown
	 */
	public boolean useWebColors() {
		return useWebColors.isSelected();
	}

	/**
	 * Set the display of the color scheme markers.
	 * 
	 * @param disp
	 *            true to display the color scheme markers.
	 */
	public void setDisplayScheme(boolean disp) {
		displayScheme = disp;
	}

	/**
	 * Get the selected colors hue
	 * 
	 * @return the selected hue in the range 0-255
	 */
	public int getHue() {
		try {
			return Integer.parseInt(hueEdit.getText());
		} catch (NumberFormatException e) {
		}

		return 128;
	}

	/**
	 * Set the selected hue
	 * 
	 * @param h
	 *            the selected hue in the range 0-255
	 */
	public void setHue(int h) {
		try {
			if (h < 0)
				h = 360 + h;

			int selHue = Math.max(0, Math.min(h, 360));
			hueEdit.setText(Integer.toString(selHue));
			resetColor();
		} catch (NumberFormatException e) {
		}
	}

	/**
	 * Get the selected colors saturation
	 * 
	 * @return the selected saturation in the range 0-255
	 */
	public int getSaturation() {
		try {
			return Integer.parseInt(satEdit.getText());
		} catch (NumberFormatException e) {
		}

		return 128;
	}

	/**
	 * Get the selected colors brightness
	 * 
	 * @return the selected brightness in the range 0-255
	 */
	public int getBrightness() {
		try {
			return Integer.parseInt(brightEdit.getText());
		} catch (NumberFormatException e) {
		}

		return 128;
	}

	/**
	 * Set the Itten color scheme to use
	 * 
	 * @param scheme
	 *            
    *
  • -1 for no scheme display
  • *
  • 0 for a monchromatic color scheme: MONOCHROMATIC_SCHEME
  • *
  • 1 for a contrasting color scheme: CONTRASTING_SCHEME
  • *
  • 2 for a soft-contrasting color scheme: * SOFT_CONTRAST_SCHEME
  • *
  • 3 for a double contrasting color scheme: * DOUBLE_CONTRAST_SCHEME
  • *
  • 4 for a analogical color scheme: ANALOGIC_SCHEME
  • *
*/ public void setColorScheme(int scheme) { colorScheme = scheme; } /** * Change the hue to match the angle identified by the point (in the inner * circle). * * @param pt * the point within the inner circle */ boolean moveHue(Point pt) { if ((borderCircle.contains(pt) && !outerCircle.contains(pt)) || innerCircle.contains(pt)) { int h = getAngle(pt); hueEdit.setText(Integer.toString(h)); selectedPath = null; resetColor(); return true; } return false; } private int getAngle(Point pt) { int eX = (pt.x > 0) ? pt.x : 96; int eY = (pt.y > 0) ? pt.y : 96; int x = eX - 112; int y = eY - 114; return (int) (Math .round(((Math.atan2(-x, y) * 180.0 / Math.PI) + 180.0) % 360.0)); } public void setColor(Color c) { systemColor = null; if (c != null) { int r = c.getRed(); int g = c.getGreen(); int b = c.getBlue(); if (useWebColors.isSelected()) { r = Math.round(r / 51) * 51; g = Math.round(g / 51) * 51; b = Math.round(b / 51) * 51; } chooserColor = new ModelColor(r, g, b); } // else c = new Color(chooserColor.R, chooserColor.G, chooserColor.B); float[] oldValues = values; values = c.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), values); if (values[1] == 0.0F) { s = values[1]; b = values[2]; } else if (values[2] == 0.0F) { b = values[2]; } else { h = values[0]; s = values[1]; b = values[2]; } h = Math.min(Math.max(h, 0.0), 1.0); s = Math.min(Math.max(s, 0.0), 1.0); b = Math.min(Math.max(b, 0.0), 1.0); if (values[1] != 0.0F) { if (values[1] != 0.0F) setHue(); setSaturation(); } setBrightness(); busy = true; brightnessSlider.setValue(Integer.parseInt(brightEdit.getText())); saturationSlider.setValue(Integer.parseInt(satEdit.getText())); busy = false; baseColorLabel.setBackground(new Color(chooserColor.R, chooserColor.G, chooserColor.B)); if ((0.5 * c.getRed() + c.getGreen() + 0.3 * c.getBlue()) < 220.0) baseColorLabel.setForeground(Color.white); else baseColorLabel.setForeground(Color.black); String colorStr; if (decimalRGB.isSelected()) { // Output decimal values colorStr = " " + Integer.toString(c.getRed()) + "." + Integer.toString(c.getGreen()) + "." + Integer.toString(c.getBlue()); } else { // Output HEX values colorStr = " " + ModelColor.toHexString(c.getRed()) + ModelColor.toHexString(c.getGreen()) + ModelColor.toHexString(c.getBlue()); } baseColorLabel.setText(colorStr); baseColorEdit.setText(colorStr); ChangeEvent evt = new ChangeEvent(this); int numListeners = changeListeners.size(); for (int i = 0; i < numListeners; i++) { ChangeListener l = changeListeners.get(i); l.stateChanged(evt); } if (hasChooser) getColorSelectionModel().setSelectedColor(c); } /** * Get the selected color * * @return the color */ public Color getColor() { return new Color(chooserColor.R, chooserColor.G, chooserColor.B); } /** * Get the chooser color * * @return * the chooser color */ public ModelColor getChooserColour() { return chooserColor; } /** * Set the value of the hue edit to match the current color */ private void setHue() { hueEdit.setText(Integer.toString(chooserColor.getHue())); } /** * Set the value of the saturartion edit to match the current color */ private void setSaturation() { satEdit.setText(Integer.toString((int) (100.0 * chooserColor.S))); } /** * Set the value of the brightness edit to match the current color */ private void setBrightness() { brightEdit.setText(Integer.toString((int) (100.0 * chooserColor.V))); } /** * Respond to action events for the edit fields */ @Override public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == resetBtn) resetColorWheel(); else if (source instanceof JMenuItem) { // A popup menu item has been selected Color sysColor = getSystemColor(((JMenuItem) source).getText()); if (sysColor != null) setColor(sysColor); resetColor(); systemColor = sysColor; if (hasChooser) { hasChooser = false; getColorSelectionModel().setSelectedColor(systemColor); hasChooser = true; } return; } else if (source == useWebColors) { boolean snap = useWebColors.isSelected(); chooserColor.setWebSnap(snap); if (snap) resetColor(); else { // Drop through to the next block to reset the internal color values source = baseColorEdit; } } else if (source == baseColorEdit) { String hex = baseColorEdit.getText().trim(); if (hex.length() == 0) resetColor(); else if (decimalRGB.isSelected()) { int pos = 0; try { int r = 255; int g = 0; int b = 0; int pos2 = hex.indexOf('.', pos); if (pos2 > 0) { r = Integer.parseInt(hex.substring(pos, pos2)); pos = ++pos2; pos2 = hex.indexOf('.', pos); if (pos2 > 0) { g = Integer.parseInt(hex.substring(pos, pos2)); pos = ++pos2; if (pos2 < hex.length()) b = Integer.parseInt(hex.substring(pos)); } } setColor(new Color(r, g, b)); } catch (NumberFormatException nfe) { setColor(Color.red); baseColorEdit.setText("255.0.0"); } } else { for (int i = hex.length(); i < 6; i++) hex += "0"; try { setColor(new Color(ModelColor.hex2dec(hex.substring(0, 2)), ModelColor.hex2dec(hex.substring(2, 4)), ModelColor .hex2dec(hex.substring(4, 6)))); } catch (NumberFormatException nfe) { setColor(Color.red); baseColorEdit.setText("FF0000"); } } } else resetColor(); } /** * Reset the displayed color to the color specified by the edit fields */ private void resetColor() { if (chooserColor != null) { if (!busy) { busy = true; int h = 0; try { h = Integer.parseInt(hueEdit.getText()); selectedPath = null; } catch (NumberFormatException nfe) { hueEdit.setText("0"); } if (h >= 360) { h = h % 360; hueEdit.setText(Integer.toString(h)); } if (h < 0) { h = (int) ((h + (Math.floor(-h / 360) + 1) * 360) % 360); hueEdit.setText(Integer.toString(h)); } double s = 1.0; try { s = Integer.parseInt(satEdit.getText()) / 100.0; } catch (NumberFormatException nfe) { satEdit.setText("100"); } if (s > 1 || s < 0) { s = (s < 0) ? 0 : 1; satEdit.setText(Integer.toString((int) (s * 100.0))); } double v = 1.0; try { v = Integer.parseInt(brightEdit.getText()) / 100.0; } catch (NumberFormatException nfe) { brightEdit.setText("100"); } if (v > 1 || v < 0) { v = (v < 0) ? 0 : 1; brightEdit.setText(Integer.toString((int) (v * 100.0))); } if (shouldAdjustWheel()) { saturationMultipler = s; brightnessMultipler = v; } if (selectedIttenColours != null) selectedIttenColours[0].setHSV(h, s, v); chooserColor.setHSV(h, s, v); busy = false; } setColor(null); } } /** * Invoked when the mouse button has been clicked (pressed and released) on * a component. */ @Override public void mouseClicked(MouseEvent e) { Object src = e.getSource(); if (src == imagePicker) { Point pt = e.getPoint(); if (borderCircle.contains(pt)) { selectedColor = rolloverColor; selectedPath = rolloverPath; if (!moveHue(pt)) { if (outerCircle.contains(pt)) { int width = imagePicker.getWidth(); int center = width / 2; int dx = Math.abs(pt.x - center); int dy = Math.abs(pt.y - center); double dr = Math.pow((dx * dx + dy * dy), 0.5); dr -= ringThickness * 1.5; int bandIdx = (int) (dr / ringThickness); int hue = 0; int bandOffset = bandIdx * ModelColor.NUM_SEGMENTS; for (int i = 0; i < ModelColor.NUM_SEGMENTS; i++) { if (paths[bandOffset + i].contains(pt)) hue = i * 15; } int hueInc = (hue / 15) % 2; // hue -= hue % 15; ModelColor mc = new ModelColor(hue, ModelColor.SATURATION_BANDS[bandIdx], ModelColor.BRIGHTNESS_BANDS[bandIdx + 1 - hueInc]); mc = new ModelColor(mc.H, saturationMultipler * mc.S, brightnessMultipler * mc.V); Color pixelColor = new Color(mc.getRed(), mc.getGreen(), mc.getBlue()); if (!pixelColor.equals(Color.white)) setColor(pixelColor); } } } } // repaint for synchronizing the hue marker if (displayScheme) imagePicker.repaint(); } /** * Invoked when a mouse button has been pressed on a component. */ @Override public void mousePressed(MouseEvent e) { imagePicker.repaint(); } /** * Invoked when a mouse button has been released on a component. */ @Override public void mouseReleased(MouseEvent e) { } /** * Invoked when the mouse enters a component. */ @Override public void mouseEntered(MouseEvent e) { } /** * Invoked when the mouse exits a component. */ @Override public void mouseExited(MouseEvent e) { rolloverPath = null; repaint(); } /** * Invoked when the mouse exits a component. */ @Override public void mouseMoved(MouseEvent e) { GeneralPath oldPath = rolloverPath; rolloverPath = null; if (e.getSource() == imagePicker) { Point pt = e.getPoint(); if (paths != null) { int numPaths = paths.length; for (int i = 0; i < numPaths; i++) { if (paths[i].contains(pt.x, pt.y)) { rolloverPath = paths[i]; ModelColor[][] baseColors = ModelColor.getBaseColors(); int ring = i / ModelColor.NUM_SEGMENTS; ModelColor modelColor = baseColors[i % ModelColor.NUM_SEGMENTS][ring]; if (adjustRollover) modelColor = new ModelColor(modelColor.H, saturationMultipler * modelColor.S, brightnessMultipler * modelColor.V); rolloverColor = new Color(modelColor.getRed(), modelColor.getGreen(), modelColor.getBlue()); if (ring < 4) rolloverColor = rolloverColor.darker(); else rolloverColor = rolloverColor.brighter().brighter(); break; } } } } if (rolloverPath != oldPath) repaint(); } /** * Move the sliders in rsponse to the mouse wheel */ @Override public void mouseWheelMoved(MouseWheelEvent e) { Object src = e.getSource(); ctrlKeyDown = e.isControlDown(); int notches = e.getWheelRotation(); if (src == brightnessSlider) { brightnessSlider .setValue(brightnessSlider.getValue() - 2 * notches); } else if (src == saturationSlider) { saturationSlider .setValue(saturationSlider.getValue() + 2 * notches); } else if (src == imagePicker) { setHue(getHue() + 2 * notches); } ctrlKeyDown = false; } /** * Invoked when the mouse exits a component. */ @Override public void mouseDragged(MouseEvent e) { ctrlKeyDown = e.isControlDown(); } /** * Invoked when the target of the listener has changed its state. * * @param e * a ChangeEvent object */ @Override public void stateChanged(ChangeEvent e) { Object source = e.getSource(); if (source == saturationSlider) { satEdit.setText(Integer.toString(saturationSlider.getValue())); resetColor(); } else if (source == brightnessSlider) { brightEdit.setText(Integer.toString(brightnessSlider.getValue())); resetColor(); } if (hasChooser) { getColorSelectionModel().setSelectedColor( new Color(chooserColor.getRed(), chooserColor.getGreen(), chooserColor.getBlue())); } ctrlKeyDown = false; } @Override protected void buildChooser() { } @Override public String getDisplayName() { return "Xoetrope Color Wheel"; } @Override public Icon getLargeDisplayIcon() { return UIManager.getIcon("ColorChooser.colorWheelIcon"); } @Override public Icon getSmallDisplayIcon() { return getLargeDisplayIcon(); } @Override public Dimension getPreferredSize() { return new Dimension(255, 328); } @Override public void updateChooser() { if (hasChooser) { Color selected = getColorFromModel(); if (selected == null) { setSelectedColors(new ModelColor[0]); setColor(null); } else { ModelColor selectedModelColor = new ModelColor(selected.getRed(), selected.getGreen(), selected.getBlue()); setSelectedColors(new ModelColor[] { selectedModelColor }); setColor(selected); } } } @Override public void installChooserPanel(JColorChooser enclosingChooser) { hasChooser = (enclosingChooser != null); super.installChooserPanel(enclosingChooser); // if runs in the color chooser, set the hue marker this.setDisplayScheme(true); } // -ColorWheel inner // class------------------------------------------------------ /** * A class that wraps the image of the color wheel and draws markers for the * selected color scheme */ class ColorWheel extends JLabel { public ColorWheel() { } /** * Draw markers for the selected color scheme */ @Override public void paintComponent(Graphics g) { super.paintComponent(g); paintWheel((Graphics2D) g); if (displayScheme) { double x, y; int selIdx = colorScheme;// > 0 ? 1 : 0; int numColours = Math.min(selIdx + 1, 4); for (int i = 0; i < numColours; i++) { double r = (selectedIttenColours[i].H - 90.0) / 360.0 * 2.0 * Math.PI; x = Math.round(111.0 + 110.0 * Math.cos(r)); y = Math.round(111.0 + 110.0 * Math.sin(r)); g.setColor(Color.gray); g.fillOval((int) x, (int) y, 4, 4); g.setColor(Color.darkGray); g.drawOval((int) x, (int) y, 4, 4); } } } public void paintWheel(Graphics2D g2d) { // Store the paths for detecting the area with the mouse click. if (paths == null) paths = new GeneralPath[ModelColor.NUM_COLOR_RINGS * ModelColor.NUM_SEGMENTS]; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); ModelColor[][] baseColors = ModelColor.getBaseColors(); int idx = 0; double width = getWidth() - 1; double center = width / 2.0; ringThickness = width / ((ModelColor.NUM_COLOR_RINGS + 2) * 2); double fontHeight = ringThickness / 2.0; double inset = ringThickness / 2.0; // Paint the outer band g2d.setColor(new Color(228, 228, 228)); Arc2D.Double innerArc = new Arc2D.Double(inset, inset, width - inset - inset, width - inset - inset, 0.0, 360.0, Arc2D.OPEN); Arc2D.Double outerArc = new Arc2D.Double(0.0, 0.0, width, width, 360.0, -360.0, Arc2D.OPEN); GeneralPath gp = new GeneralPath(); gp.append(innerArc, true); gp.append(outerArc, true); gp.closePath(); g2d.fill(gp); g2d.setColor(Color.black); g2d.setStroke(new BasicStroke(0.3F)); g2d.draw(outerArc); // Paint the inner yellow arc g2d.setColor(new Color(255, 253, 220)); innerArc = new Arc2D.Double(center - ringThickness / 2.0, center - ringThickness / 2.0, ringThickness, ringThickness, -30.0, 180.0, Arc2D.OPEN); outerArc = new Arc2D.Double(center - ringThickness, center - ringThickness, ringThickness * 2, ringThickness * 2, 150.0, -180.0, Arc2D.OPEN); gp = new GeneralPath(); gp.append(innerArc, true); gp.append(outerArc, true); gp.closePath(); g2d.fill(gp); // Paint the inner blue arc g2d.setColor(new Color(202, 230, 252)); innerArc = new Arc2D.Double(center - ringThickness / 2.0, center - ringThickness / 2.0, ringThickness, ringThickness, 150.0, 180.0, Arc2D.OPEN); outerArc = new Arc2D.Double(center - ringThickness, center - ringThickness, ringThickness * 2, ringThickness * 2, 330.0, -180.0, Arc2D.OPEN); gp = new GeneralPath(); gp.append(innerArc, true); gp.append(outerArc, true); gp.closePath(); g2d.fill(gp); // Draw the 'dial' g2d.setColor(Color.black); AffineTransform identityTransform = g2d.getTransform(); AffineTransform at = ((AffineTransform) identityTransform.clone()); at.translate(center, center); at.rotate(Math.PI / 6.0); g2d.setTransform(at); gp = new GeneralPath(); gp.moveTo((float) (-ringThickness / 2.0), 0.0F); gp.lineTo((float) (-ringThickness * 1.2), 0.0F); gp.lineTo((float) (-ringThickness * 1.2), (float) (-fontHeight)); gp.lineTo((float) (-ringThickness * 1.4), (float) (-fontHeight + ringThickness * 0.2)); gp.moveTo((float) (-ringThickness * 1.2), (float) (-fontHeight)); gp.lineTo((float) (-ringThickness), (float) (-fontHeight + ringThickness * 0.2)); g2d.draw(gp); gp = new GeneralPath(); gp.moveTo((float) (ringThickness / 2.0), 0.0F); gp.lineTo((float) (ringThickness * 1.2), 0.0F); gp.lineTo((float) (ringThickness * 1.2), (float) (fontHeight)); gp.lineTo((float) (ringThickness * 1.4), (float) (fontHeight - ringThickness * 0.2)); gp.moveTo((float) (ringThickness * 1.2), (float) (fontHeight)); gp.lineTo((float) (ringThickness), (float) (fontHeight - ringThickness * 0.2)); g2d.draw(gp); // Draw the tick marks double r1 = center; double r2 = r1 - fontHeight; double r3 = r1 - ringThickness / 2.3; double r4 = r1 + ringThickness / 2.7; // The angles for cos and sin are in radians double inc = Math.PI / 12.0; // double fullArc = Math.PI * 2.0; g2d.setColor(Color.black); for (int i = 0; i < ModelColor.NUM_SEGMENTS; i++) { double angle = i * inc; double sin = Math.sin(angle); double cos = Math.cos(angle); gp = new GeneralPath(); if ((width > 200) && (i % 2 == 0)) { AttributedString as = new AttributedString("" + (((i * 15) + 90) % 360) + "�"); as.addAttribute(TextAttribute.FAMILY, fontFamily); as.addAttribute(TextAttribute.SIZE, (float) (fontHeight)); as.addAttribute(TextAttribute.FOREGROUND, Color.black); at = ((AffineTransform) identityTransform.clone()); at.translate((center + fontHeight / 5.0 + r3 * cos), (center + r3 * sin)); at.rotate(angle + Math.PI / 2.0); g2d.setTransform(at); g2d.drawString(as.getIterator(), 0.0F, 0.0F); } else { g2d.setTransform(identityTransform); gp.moveTo((float) (center + r1 * cos), (float) (center + r1 * sin)); gp.lineTo((float) (center + r2 * cos), (float) (center + r2 * sin)); g2d.draw(gp); } } // Paint the rings / star // int pathIdx = 0; for (int i = 0; i < ModelColor.NUM_COLOR_RINGS; i++) { double outerX = inset + (ModelColor.NUM_COLOR_RINGS - (i + 1)) * ringThickness; double outerW = width - outerX - outerX; double innerX = outerX + ringThickness; double innerW = outerW - 2 * ringThickness; for (int j = 0; j < ModelColor.NUM_SEGMENTS; j++) { ModelColor modelColor = baseColors[j][i]; modelColor = new ModelColor(modelColor.H, saturationMultipler * modelColor.S, brightnessMultipler * modelColor.V); Color c = new Color(modelColor.getRed(), modelColor .getGreen(), modelColor.getBlue()); g2d.setColor(c); double startAngle = ((82.5 - (j * 15.0)) + 360) % 360.0; double delta1 = j % 2 == 0 ? arcDelta[i] : -arcDelta[i]; double delta2 = j % 2 == 0 ? arcDelta[i + 1] : -arcDelta[i + 1]; innerArc = new Arc2D.Double(innerX, innerX, innerW, innerW, startAngle + delta1, 15.0 - 2.0 * delta1, Arc2D.OPEN); outerArc = new Arc2D.Double(outerX, outerX, outerW, outerW, startAngle + 15.0 - delta2, -15.0 + 2.0 * delta2, Arc2D.OPEN); gp = new GeneralPath(); gp.append(innerArc, true); gp.append(outerArc, true); gp.closePath(); g2d.fill(gp); paths[idx++] = gp; } } // Paint the labels g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); if (width > 200) { double angle = (Math.PI / 6.0) - (Math.PI / 2.0); double angle2 = angle - 0.055; double sin = Math.sin(angle2); double cos = Math.cos(angle2); AttributedString as = new AttributedString(getLabel( "Xoetrope.warm", "WARM")); as.addAttribute(TextAttribute.FAMILY, fontFamily); as.addAttribute(TextAttribute.SIZE, (float) (ringThickness / 1.5)); as.addAttribute(TextAttribute.FOREGROUND, new Color(92, 0, 0)); at = ((AffineTransform) identityTransform.clone()); at.translate((center + fontHeight / 5.0 + r4 * cos), (center + r4 * sin)); at.rotate(angle + Math.PI / 2.0 + 0.05); g2d.setTransform(at); g2d.drawString(as.getIterator(), 0.0F, 0.0F); angle += Math.PI; sin = Math.sin(angle); cos = Math.cos(angle); as = new AttributedString(getLabel("Xoetrope.cold", "COLD")); as.addAttribute(TextAttribute.FAMILY, fontFamily); as.addAttribute(TextAttribute.SIZE, (float) (ringThickness / 1.5)); as.addAttribute(TextAttribute.FOREGROUND, new Color(0, 0, 92)); at = ((AffineTransform) identityTransform.clone()); at.translate((center + fontHeight / 5.0 + r4 * cos), (center + r4 * sin)); at.rotate(angle + Math.PI / 2.0 + 0.05); g2d.setTransform(at); g2d.drawString(as.getIterator(), 0.0F, 0.0F); angle = Math.PI; sin = Math.sin(angle); cos = Math.cos(angle); as = new AttributedString(getLabel("Xoetrope.saturation", "Saturation")); as.addAttribute(TextAttribute.FAMILY, fontFamily); as.addAttribute(TextAttribute.SIZE, (float) (ringThickness / 1.3)); as.addAttribute(TextAttribute.FOREGROUND, UIManager .getColor("Label.foreground")); at = ((AffineTransform) identityTransform.clone()); at.translate((width - fontHeight), (width)); at.rotate(angle + Math.PI / 2.0); g2d.setTransform(at); g2d.drawString(as.getIterator(), 0.0F, 0.0F); String brightnessText = getLabel("Xoetrope.brightness", "Brightness"); as = new AttributedString(brightnessText); as.addAttribute(TextAttribute.FAMILY, fontFamily); as.addAttribute(TextAttribute.SIZE, (float) (ringThickness / 1.3)); as.addAttribute(TextAttribute.FOREGROUND, UIManager .getColor("Label.foreground")); at = ((AffineTransform) identityTransform.clone()); at.translate((width - fontHeight), (ringThickness * brightnessText.length() / 2.3)); at.rotate(angle + Math.PI / 2.0); g2d.setTransform(at); g2d.drawString(as.getIterator(), 0.0F, 0.0F); } g2d.setTransform(identityTransform); if (showRollovers) { g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (rolloverPath != null) { g2d.setColor(rolloverColor); g2d.setStroke(new BasicStroke(1.5F)); g2d.draw(rolloverPath); } if (selectedPath != null) { g2d.setColor(selectedColor); g2d.setStroke(new BasicStroke(1.0F)); g2d.draw(selectedPath); } } } } // End ColorWheel inner class // ------------------------------------------------ // ---------------------------------------------------------------------------- private class ColorDocumentListener implements DocumentListener { private JTextField originator; private static final String MARKER = "Xoetrope.XUI.ColorWheel.DocumentEvent"; public ColorDocumentListener(JTextField originator) { this.originator = originator; } /** * This method is called after an insert into the document */ @Override public void insertUpdate(DocumentEvent evt) { synchronize(evt); } /** * This method is called after a removal from the document */ @Override public void removeUpdate(DocumentEvent evt) { synchronize(evt); } /** * This method is called after one or more attributes have changed. This * method is not called when characters are inserted with attributes. */ @Override public void changedUpdate(DocumentEvent evt) { synchronize(evt); } public void synchronize(DocumentEvent evt) { boolean _hasAllValues = true; if (hueEdit.getText().length() == 0) _hasAllValues = false; if (brightEdit.getText().length() == 0) _hasAllValues = false; if (satEdit.getText().length() == 0) _hasAllValues = false; final boolean hasAllValues = _hasAllValues; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { useWebColors.setEnabled(hasAllValues); decimalRGB.setEnabled(hasAllValues); } }); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { // the below use of client property is to prevent // infinite event loop (resetColor evetually changes // the text boxes) if (hasAllValues && originator.hasFocus()) { if (Boolean.TRUE.equals(originator .getClientProperty(MARKER))) { originator.putClientProperty(MARKER, null); } else { originator.putClientProperty(MARKER, Boolean.TRUE); resetColor(); } } // repaint for synchronizing the hue marker if (displayScheme) imagePicker.repaint(); } }); } } // ---------------------------------------------------------------------------- public static void setLabelBundle(ResourceBundle labelBundle) { ColorWheelPanel.labelBundle = labelBundle; } private static String getLabel(String labelName, String defaultValue) { if (ColorWheelPanel.labelBundle == null) return defaultValue; try { return ColorWheelPanel.labelBundle.getString(labelName); } catch (MissingResourceException mre) { return defaultValue; } } /** * Show a popup menu with the list of system colors * * @param p * the location to display the popup */ private void showSystemColorList(Point p) { JPopupMenu popupMenu = new JPopupMenu(); String[] systemColors = { "activeCaption", "desktop", "activeCaptionText", "activeCaptionBorder", "inactiveCaption", "inactiveCaptionText", "inactiveCaptionBorder", "window", "windowBorder", "windowText", "menu", "menuText", "text", "textText", "textHighlight", "textHighlightText", "textInactiveText", "control", "controlText", "controlHighlight", "controlLtHighlight", "controlShadow", "controlDkShadow", "scrollbar", "info", "infoText", "white", "lightGray", "gray", "darkGray", "black", "red", "pink", "orange", "yellow", "green", "magenta", "cyan", "blue" }; for (int i = 0; i < systemColors.length; i++) { if (systemColors[i].equals("white")) { popupMenu.addSeparator(); continue; } JMenuItem mi = new JMenuItem(systemColors[i]); mi.addActionListener(this); BufferedImage image = new BufferedImage(8, 8, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); g.setColor(getSystemColor(systemColors[i])); g.fillRect(0, 0, 8, 8); g.setColor(SystemColor.windowBorder); g.drawRect(0, 0, 7, 7); g.dispose(); Icon icon = new ImageIcon(image); mi.setIcon(icon); popupMenu.add(mi); } popupMenu.show(this, p.x, p.y); } /** * Get the named system color * * @param temp * the color name * @return the color value or null if the name is not recognized */ public Color getSystemColor(String temp) { Color clr = null; if (temp.equals("activeCaption")) clr = SystemColor.activeCaption; else if (temp.equals("desktop")) clr = SystemColor.desktop; else if (temp.equals("activeCaptionText")) clr = SystemColor.activeCaptionText; else if (temp.equals("activeCaptionBorder")) clr = SystemColor.activeCaptionBorder; else if (temp.equals("inactiveCaption")) clr = SystemColor.inactiveCaption; else if (temp.equals("inactiveCaptionText")) clr = SystemColor.inactiveCaptionText; else if (temp.equals("inactiveCaptionBorder")) clr = SystemColor.inactiveCaptionBorder; else if (temp.equals("window")) clr = SystemColor.window; else if (temp.equals("windowBorder")) clr = SystemColor.windowBorder; else if (temp.equals("windowText")) clr = SystemColor.windowText; else if (temp.equals("menu")) clr = SystemColor.menu; else if (temp.equals("menuText")) clr = SystemColor.menuText; else if (temp.equals("text")) clr = SystemColor.text; else if (temp.equals("textText")) clr = SystemColor.textText; else if (temp.equals("textHighlight")) clr = SystemColor.textHighlight; else if (temp.equals("textHighlightText")) clr = SystemColor.textHighlightText; else if (temp.equals("textInactiveText")) clr = SystemColor.textInactiveText; else if (temp.equals("control")) clr = SystemColor.control; else if (temp.equals("controlText")) clr = SystemColor.controlText; else if (temp.equals("controlHighlight")) clr = SystemColor.controlHighlight; else if (temp.equals("controlLtHighlight")) clr = SystemColor.controlLtHighlight; else if (temp.equals("controlShadow")) clr = SystemColor.controlShadow; else if (temp.equals("controlDkShadow")) clr = SystemColor.controlDkShadow; else if (temp.equals("scrollbar")) clr = SystemColor.scrollbar; else if (temp.equals("info")) clr = SystemColor.info; else if (temp.equals("infoText")) clr = SystemColor.infoText; else if (temp.equals("white")) clr = Color.white; else if (temp.equals("lightGray")) clr = Color.lightGray; else if (temp.equals("gray")) clr = Color.gray; else if (temp.equals("darkGray")) clr = Color.darkGray; else if (temp.equals("black")) clr = Color.black; else if (temp.equals("red")) clr = Color.red; else if (temp.equals("pink")) clr = Color.pink; else if (temp.equals("orange")) clr = Color.orange; else if (temp.equals("yellow")) clr = Color.yellow; else if (temp.equals("green")) clr = Color.green; else if (temp.equals("magenta")) clr = Color.magenta; else if (temp.equals("cyan")) clr = Color.green; else if (temp.equals("blue")) clr = Color.blue; return clr; } /** * Should the color wheeel's colors be adjusted * * @return true if the colors should change to match the brightness and * saturation */ private boolean shouldAdjustWheel() { if (adjustWheel == NEVER_ADJUST) return false; else if (adjustWheel == ALWAYS_ADJUST) return true; else if (ctrlKeyDown) return true; return false; } /** * Get the adjust color wheel flag. * * @return the adjustment mode */ public int getAdjustWheel() { return adjustWheel; } /** * Set the adjust color wheel flag. * * @param state * the color wheel's new adjustment mode ( CTRL_ADJUST | * ALWAYS_ADJUST | NEVER_ADJUST ); */ public void setAdjustWheel(int state) { adjustWheel = state; } /** * Get the adjust rollover color flag. * * @return the adjustment mode */ public boolean getRollover() { return adjustRollover; } /** * Set the adjust rollover color flag. * * @param state * the rollover's new adjustment mode ( true | false ); */ public void setRollover(boolean state) { adjustRollover = state; } /** * Reset the brightness and saturation multipliers for the ColorWheel. */ public void resetColorWheel() { saturationMultipler = brightnessMultipler = 1.0; resetColor(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy