/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Part of the Processing project - http://processing.org Copyright (c) 2012-15 The Processing Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package processing.mode.java.tweak; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import javax.swing.Box; import javax.swing.JComponent; import javax.swing.JFrame; public class ColorSelector { int hue, saturation, brightness; public JFrame frame; public ColorControlBox colorBox; ColorSelectorBox selectorBox; ColorSelectorSlider selectorSlider; SelectorTopBar topBar; public ColorSelector(ColorControlBox colorBox) { this.colorBox = colorBox; createFrame(); } public void createFrame() { frame = new JFrame(); frame.setBackground(Color.BLACK); Box box = Box.createHorizontalBox(); box.setBackground(Color.BLACK); selectorSlider = new ColorSelectorSlider(); if (!colorBox.isBW) { selectorBox = new ColorSelectorBox(); box.add(selectorBox); } box.add(Box.createHorizontalGlue()); box.add(selectorSlider, BorderLayout.CENTER); box.add(Box.createHorizontalGlue()); frame.getContentPane().add(box, BorderLayout.CENTER); frame.pack(); frame.setResizable(false); frame.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); } public void show(int x, int y) { frame.setLocation(x, y); frame.setVisible(true); frame.repaint(); } public void hide() { this.colorBox = null; frame.setVisible(false); } public void refreshColor() { if (!colorBox.ilegalColor) { setColor(colorBox.color); } } public void setColor(Color c) { if (selectorBox != null) { selectorBox.setToColor(c); } selectorSlider.setToColor(c); repaintSelector(); } public void satBrightChanged() { repaintSelector(); } public void hueChanged() { if (selectorBox != null) { selectorBox.renderBack(); } repaintSelector(); } public void repaintSelector() { if (selectorBox != null) { selectorBox.repaint(); } selectorSlider.repaint(); } // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . class ColorSelectorBox extends JComponent { int lastX, lastY; BufferedImage backImg; ColorSelectorBox() { if (!colorBox.ilegalColor) { setToColor(colorBox.color); } renderBack(); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { updateMouse(e); } }); addMouseMotionListener(new MouseAdapter() { public void mouseDragged(MouseEvent e) { updateMouse(e); } }); } public void paintComponent(Graphics g) { g.drawImage(backImg, 0, 0, this); Graphics2D g2 = (Graphics2D) g; // otherwise the oval is hideous // TODO make a proper hidpi version of all this g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(lastY < 128 ? Color.BLACK : Color.WHITE); AffineTransform tx = g2.getTransform(); g2.translate(lastX, lastY); //g2.drawOval(0, 0, 5, 5); g2.drawOval(-3, -3, 6, 6); g2.drawLine(-8, 0, -6, 0); g2.drawLine(6, 0, 8, 0); g2.drawLine(0, -8, 0, -6); g2.drawLine(0, 6, 0, 8); g2.setTransform(tx); } public void renderBack() { int[] pixels = new int[256 * 256]; int index = 0; for (int j = 0; j < 256; j++) { for (int i = 0; i < 256; i++) { pixels[index++] = // color(hue, i, 255-j); Color.HSBtoRGB(hue / 255f, (i / 255f), (255-j)/255f); } } backImg = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB); backImg.getRaster().setDataElements(0, 0, 256, 256, pixels); } public void setToColor(Color c) { // set selector color float hsb[] = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); saturation = (int) (hsb[1] * 255); brightness = (int) (hsb[2] * 255); lastX = saturation; lastY = 255 - brightness; } void updateMouse(MouseEvent event) { int mouseX = event.getX(); int mouseY = event.getY(); if (mouseX >= 0 && mouseX < 256 && mouseY >= 0 && mouseY < 256) { lastX = mouseX; lastY = mouseY; updateColor(); } } void updateColor() { saturation = lastX; brightness = 255 - lastY; satBrightChanged(); colorBox.selectorChanged(hue, saturation, brightness); } public Dimension getPreferredSize() { return new Dimension(256, 256); } public Dimension getMinimumSize() { return getPreferredSize(); } public Dimension getMaximumSize() { return getPreferredSize(); } } // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . class ColorSelectorSlider extends JComponent { final int WIDE = 30; BufferedImage backImg; int lastY; ColorSelectorSlider() { // size(30, 255); // noLoop(); // colorMode(HSB, 255, 255, 255); // strokeWeight(1); // noFill(); // loadPixels(); if (!colorBox.ilegalColor) { setToColor(colorBox.color); } // draw the slider background renderBack(); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { updateMouse(e); } }); addMouseMotionListener(new MouseAdapter() { public void mouseDragged(MouseEvent e) { updateMouse(e); } }); } public void paintComponent(Graphics g) { g.drawImage(backImg, 0, 0, this); Graphics2D g2 = (Graphics2D) g; // if (colorBox.isBW) { // stroke(lastY<128 ? 0 : 255); // } // else { // stroke(0); // } if (colorBox.isBW && lastY >= 128) { g2.setColor(Color.WHITE); } else { g2.setColor(Color.BLACK); } AffineTransform tx = g2.getTransform(); g2.translate(0, lastY); // draw left bracket // beginShape(); // vertex(5, -2); // vertex(1, -2); // vertex(1, 2); // vertex(5, 2); // endShape(); g.drawRect(1, -2, 6, 4); // draw middle lines g.drawLine(13, 0, 17, 0); g.drawLine(15, -2, 15, 2); // draw right bracket // beginShape(); // vertex(24, -2); // vertex(28, -2); // vertex(28, 2); // vertex(24, 2); // endShape(); g.drawRect(24, -2, 4, 4); g2.setTransform(tx); /* if (colorBox.isBW) { // stroke(255); // rect(0, 0, 29, 254); g.setColor(Color.WHITE); g.drawRect(0, 0, WIDE, 255); } else { // stroke(0); // line(0, 0, 0, 255); // line(29, 0, 29, 255); g.setColor(Color.BLACK); g.drawLine(0, 0, 0, 255); g.drawLine(29, 0, 29, 255); } */ } void renderBack() { int[] pixels = new int[WIDE * 256]; int index = 0; int argb = 0; for (int j = 0; j < 256; j++) { if (colorBox.isBW) { int gray = 255 - j; argb = 0xff000000 | (gray << 16) | (gray << 8) | gray; } else { // color(255-j, 255, 255); argb = Color.HSBtoRGB((255 - j) / 255f, 1, 1); } for (int i = 0; i < WIDE; i++) { pixels[index++] = argb; } } backImg = new BufferedImage(WIDE, 256, BufferedImage.TYPE_INT_RGB); backImg.getRaster().setDataElements(0, 0, WIDE, 256, pixels); } void setToColor(Color c) { // set slider position if (colorBox.isBW) { hue = c.getRed(); } else { float hsb[] = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); hue = (int)(hsb[0]*255); } lastY = 255 - hue; } void updateMouse(MouseEvent event) { int mouseY = event.getY(); if (mouseY >= 0 && mouseY < 256) { lastY = mouseY; updateColor(); } } public void updateColor() { hue = 255 - lastY; hueChanged(); colorBox.selectorChanged(hue, saturation, brightness); } public Dimension getPreferredSize() { return new Dimension(30, 255); } public Dimension getMinimumSize() { return getPreferredSize(); } public Dimension getMaximumSize() { return getPreferredSize(); } } // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . public class SelectorTopBar extends JComponent { int barWidth; int barHeight = 16; public SelectorTopBar(int w) { barWidth = w; } @Override public void paintComponent(Graphics g) { g.setColor(Color.GRAY); Dimension size = getSize(); g.fillRect(0, 0, size.width, size.height); } public Dimension getPreferredSize() { return new Dimension(barWidth, barHeight); } public Dimension getMinimumSize() { return getPreferredSize(); } public Dimension getMaximumSize() { return getPreferredSize(); } } }