package com.vitco.layout.content.colorchooser.components; import com.vitco.layout.content.colorchooser.basic.Settings; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.util.ArrayList; /** * A custom color slider prototype that allows for custom thumbs (cursor) and background generation. */ public abstract class ColorSliderPrototype extends JSlider { // holds the listeners private final ArrayList<ValueChangeListener> listener = new ArrayList<ValueChangeListener>(); // add a listener public final void addValueChangeListener(ValueChangeListener vcl) { listener.add(vcl); } // notify listeners private boolean blockNotify = false; private void notifyListeners() { if (!blockNotify) { for (ValueChangeListener vcl : listener) { vcl.onChange(this.changeEvent); } } } // this will NOT trigger the listeners to be notified public final void setValueWithoutRefresh(int value) { if (getValue() != value) { blockNotify = true; setValue(value); blockNotify = false; } } // allow to set a specific fixed height private Integer height = null; public void setHeight(int height) { this.height = height; } // return the set height (setHeight(...)) @Override public int getHeight() { if (height == null) { return super.getHeight(); } else { return height; } } // draw the background protected abstract void drawBackground(Graphics2D g, SliderUI sliderUI); // thumb image that is drawn private BufferedImage thumbBuffer; // setter for the thumb image public final void setThumb(BufferedImage thumb) { thumbBuffer = thumb; } // constructor public ColorSliderPrototype(final int orientation, int min, int max, int current) { super(orientation, min, max, current); // notification addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { notifyListeners(); } }); // ================ // create default thumb { final int size = 5; thumbBuffer = new BufferedImage(size * 2 + 1, size * 2 + 1, BufferedImage.TYPE_INT_ARGB); Graphics2D ig = (Graphics2D) thumbBuffer.getGraphics(); // Anti-alias ig.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (orientation != JSlider.HORIZONTAL) { //ig.rotate(-Math.PI/2, size, size); ig.setColor(Color.BLACK); ig.fillOval(0, 0, thumbBuffer.getWidth() - 1, thumbBuffer.getHeight() - 1); ig.setColor(Color.WHITE); ig.drawOval(0,0,thumbBuffer.getWidth()-1,thumbBuffer.getHeight()-1); } else { ig.setPaint(new GradientPaint(0, 1, Settings.SLIDER_KNOB_COLOR_TOP, 0, size * 2, Settings.SLIDER_KNOB_COLOR_BOTTOM, false)); ig.fillPolygon(new int[]{1, size * 2, size * 2, size, 1}, new int[]{size * 2, size * 2, size, 1, size}, 5); ig.setColor(Settings.SLIDER_KNOB_OUTLINE_COLOR); ig.setStroke(new BasicStroke(0.7f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); // line size ig.drawPolygon(new int[]{0, size * 2, size * 2, size, 0}, new int[]{size * 2, size * 2, size, 0, size}, 5); } ig.dispose(); } // =============== // create ui final SliderUI sliderUI = new SliderUI(this) { @Override public void paint(Graphics g, JComponent c) { super.paint(g, c); // draw the background drawBackground((Graphics2D) g, this); // draw the thumb if (g.getClipBounds().intersects(thumbRect)) { if (orientation == JSlider.HORIZONTAL) { // make sure the thumbRect covers the whole height thumbRect.y = 0; thumbRect.height = slider.getHeight(); // draw the thumb g.drawImage(thumbBuffer, xPositionForValue(slider.getValue()) - thumbBuffer.getWidth() / 2, slider.getHeight() - thumbBuffer.getHeight() - 1, null ); } else { // make sure the thumbRect covers the whole width thumbRect.x = 0; thumbRect.width = slider.getWidth(); // draw the thumb g.drawImage(thumbBuffer, slider.getWidth() - thumbBuffer.getWidth() - 1, yPositionForValue(slider.getValue()) - thumbBuffer.getHeight() / 2, null ); } } } }; // move the thumb to the position we pressed (instantly) addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { if (orientation == JSlider.HORIZONTAL) { setValue(sliderUI.valueForXPosition(e.getX())); } else { setValue(sliderUI.valueForYPosition(e.getY())); } repaint(); } }); // register - needs to go last setUI(sliderUI); } }