/** * This software is released as part of the Pumpernickel project. * * All com.pump resources in the Pumpernickel project are distributed under the * MIT License: * https://raw.githubusercontent.com/mickleness/pumpernickel/master/License.txt * * More information about the Pumpernickel project is available here: * https://mickleness.github.io/pumpernickel/ */ package com.pump.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.SwingConstants; import javax.swing.event.MouseInputAdapter; import javax.swing.plaf.basic.BasicSliderUI; import com.pump.swing.JColorPicker; import com.pump.swing.JColorPickerPanel; /** * This is a SliderUI designed specifically for the <code>JColorPicker</code>. * */ public class ColorPickerSliderUI extends BasicSliderUI { JColorPicker 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, JColorPicker cp) { super(b); colorPicker = cp; cp.getColorPanel().addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { ColorPickerSliderUI.this.calculateGeometry(); slider.repaint(); } }); } @Override 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); } @Override protected void calculateThumbSize() { super.calculateThumbSize(); thumbRect.height += 4; thumbRect.y -= 2; } @Override protected void calculateTrackRect() { super.calculateTrackRect(); JColorPickerPanel cp = colorPicker.getColorPanel(); int size = Math.min(JColorPickerPanel.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; } @Override public synchronized void paintTrack(Graphics g) { int mode = colorPicker.getMode(); if (mode == JColorPicker.HUE || mode == JColorPicker.BRI || mode == JColorPicker.SAT) { float[] hsb = colorPicker.getHSB(); if (mode == JColorPicker.HUE) { for (int y = 0; y < trackRect.height; y++) { float hue = ((float) y) / ((float) trackRect.height); intArray[y] = Color.HSBtoRGB(hue, 1, 1); } } else if (mode == JColorPicker.SAT) { for (int y = 0; y < trackRect.height; y++) { float sat = 1 - ((float) y) / ((float) trackRect.height); intArray[y] = Color.HSBtoRGB(hsb[0], sat, hsb[2]); } } else { for (int y = 0; y < trackRect.height; y++) { float bri = 1 - ((float) y) / ((float) trackRect.height); intArray[y] = Color.HSBtoRGB(hsb[0], hsb[1], bri); } } } else { int[] rgb = colorPicker.getRGB(); if (mode == JColorPicker.RED) { for (int y = 0; y < trackRect.height; y++) { int red = 255 - (int) (y * 255 / trackRect.height + .49); intArray[y] = (red << 16) + (rgb[1] << 8) + (rgb[2]); } } else if (mode == JColorPicker.GREEN) { for (int y = 0; y < trackRect.height; y++) { int green = 255 - (int) (y * 255 / trackRect.height + .49); intArray[y] = (rgb[0] << 16) + (green << 8) + (rgb[2]); } } else if (mode == JColorPicker.BLUE) { for (int y = 0; y < trackRect.height; y++) { int blue = 255 - (int) (y * 255 / trackRect.height + .49); intArray[y] = (rgb[0] << 16) + (rgb[1] << 8) + (blue); } } } Graphics2D g2 = (Graphics2D) g; Rectangle r = new Rectangle(6, trackRect.y, 14, trackRect.height); if (slider.hasFocus()) { PlafPaintUtils.paintFocus(g2, r, 3); } bi.getRaster().setDataElements(0, 0, 1, trackRect.height, intArray); TexturePaint p = new TexturePaint(bi, new Rectangle(0, trackRect.y, 1, bi.getHeight())); g2.setPaint(p); g2.fillRect(r.x, r.y, r.width, r.height); PlafPaintUtils.drawBevel(g2, r); } @Override public void paintFocus(Graphics g) { } /** * This overrides the default behavior for this slider and sets the thumb to * where the user clicked. From a design standpoint, users probably don't * want to scroll through several colors to get where they clicked: they * simply want the color they selected. */ MouseInputAdapter myMouseListener = new MouseInputAdapter() { @Override public void mousePressed(MouseEvent e) { slider.setValueIsAdjusting(true); updateSliderValue(e); } private void updateSliderValue(MouseEvent e) { int v; if (slider.getOrientation() == SwingConstants.HORIZONTAL) { int x = e.getX(); v = valueForXPosition(x); } else { int y = e.getY(); v = valueForYPosition(y); } slider.setValue(v); } @Override public void mouseReleased(MouseEvent e) { updateSliderValue(e); slider.setValueIsAdjusting(false); } @Override public void mouseDragged(MouseEvent e) { updateSliderValue(e); } }; @Override protected void installListeners(JSlider slider) { super.installListeners(slider); slider.removeMouseListener(trackListener); slider.removeMouseMotionListener(trackListener); slider.addMouseListener(myMouseListener); slider.addMouseMotionListener(myMouseListener); slider.setOpaque(false); } @Override protected void uninstallListeners(JSlider slider) { super.uninstallListeners(slider); slider.removeMouseListener(myMouseListener); slider.removeMouseMotionListener(myMouseListener); } }