1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
package com.explodingpixels.macwidgets.plaf;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JComponent;
import javax.swing.JSlider;
import javax.swing.plaf.basic.BasicSliderUI;
/**
* Creates a Heads Up Display (HUD) style slider, similar to that seen in various iApps
* (e.g. iPhoto).
* <br>
* <img src="../../../../../graphics/HUDSliderUI-round.png">
* <br/>
* <img src="../../../../../graphics/HUDSliderUI-pointy.png">
*/
public class HudSliderUI extends BasicSliderUI {
private static final int SLIDER_KNOB_WIDTH = 11;
private static final int SLIDER_KNOB_HEIGHT_NO_TICKS = 11;
private static final int SLIDER_KNOB_HEIGHT_WITH_TICKS = 13;
private static final int TRACK_HEIGHT = 4;
private static final Color TRACK_BACKGROUND_COLOR = new Color(143, 147, 144, 100);
private static final Color TRACK_BORDER_COLOR = new Color(255, 255, 255, 200);
private static final Color TOP_SLIDER_KNOB_COLOR = new Color(0x555555);
private static final Color BOTTOM_SLIDER_KNOB_COLOR = new Color(0x393939);
private static final Color TOP_SLIDER_KNOB_PRESSED_COLOR = new Color(0xb0b2b6);
private static final Color BOTTOM_SLIDER_KNOB_PRESSED_COLOR = new Color(0x86888b);
private static final HudPaintingUtils.ShapeProvider NO_TICKS_SHAPE_PROVIDER =
createCircularSliderKnobShapeProvider();
private static final HudPaintingUtils.ShapeProvider TICKS_SHAPE_PROVIDER =
createPointedSliderKnobShapeProvider();
public HudSliderUI(JSlider b) {
super(b);
}
@Override
protected void installDefaults(JSlider slider) {
super.installDefaults(slider);
slider.setOpaque(false);
}
@Override
protected Dimension getThumbSize() {
int sliderKnobHeight = slider.getPaintTicks()
? SLIDER_KNOB_HEIGHT_WITH_TICKS : SLIDER_KNOB_HEIGHT_NO_TICKS;
return new Dimension(SLIDER_KNOB_WIDTH, sliderKnobHeight);
}
@Override
public void paint(Graphics g, JComponent c) {
HudPaintingUtils.updateGraphicsToPaintDisabledControlIfNecessary((Graphics2D) g, c);
super.paint(g, c);
}
@Override
public void paintThumb(Graphics graphics) {
Paint paint = createSliderKnobButtonPaint(isDragging(), thumbRect.height);
HudPaintingUtils.ShapeProvider shapeProvider = slider.getPaintTicks()
? TICKS_SHAPE_PROVIDER : NO_TICKS_SHAPE_PROVIDER;
HudPaintingUtils.paintHudControlBackground((Graphics2D) graphics, thumbRect, shapeProvider,
paint);
}
@Override
public void paintTrack(Graphics graphics) {
Graphics2D graphics2d = (Graphics2D) graphics;
graphics2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
double trackY = slider.getHeight() / 2.0 - TRACK_HEIGHT / 2.0;
RoundRectangle2D track = new RoundRectangle2D.Double(
0, trackY, slider.getWidth() - 1, TRACK_HEIGHT - 1, 4, 2);
graphics.setColor(TRACK_BACKGROUND_COLOR);
graphics2d.fill(track);
graphics2d.setColor(TRACK_BORDER_COLOR);
graphics2d.draw(track);
}
@Override
protected int getTickLength() {
return 5;
}
@Override
protected void calculateThumbLocation() {
super.calculateThumbLocation();
if (slider.getOrientation() == JSlider.HORIZONTAL
&& slider.getPaintTicks()) {
// shift the thumb down three pixels if we're drawing the pointy style thumb.
thumbRect.y += 3;
} else {
// TODO handle vertical slider.
}
}
@Override
protected void calculateTickRect() {
super.calculateTickRect();
if (slider.getOrientation() == JSlider.HORIZONTAL) {
// shift the ticks down by two pixels so they aren't right up agains the track.
tickRect.y += 1;
} else {
// TODO handle vertical slider.
}
}
@Override
protected void paintMajorTickForHorizSlider(Graphics g, Rectangle tickBounds, int x) {
g.setColor(Color.WHITE);
super.paintMajorTickForHorizSlider(g, tickBounds, x);
}
@Override
public void setThumbLocation(int x, int y) {
super.setThumbLocation(x, y);
// repaint the whole slider -- it's easier than trying to figure out whats dirty, especially
// since the thumb will be drawn outside of the thumbRect (the shadow part).
slider.repaint();
}
@Override
public void paintFocus(Graphics g) {
// don't paint focus.
}
private static Paint createSliderKnobButtonPaint(boolean isPressed, int height) {
Color topColor = isPressed ? TOP_SLIDER_KNOB_PRESSED_COLOR : TOP_SLIDER_KNOB_COLOR;
Color bottomColor = isPressed ? BOTTOM_SLIDER_KNOB_PRESSED_COLOR : BOTTOM_SLIDER_KNOB_COLOR;
// compenstate for the two pixel shadow drawn below the slider thumb.
int bottomY = height - 2;
return new GradientPaint(0, 0, topColor, 0, bottomY, bottomColor);
}
/**
* Creates a simple circle.
*/
private static HudPaintingUtils.ShapeProvider createCircularSliderKnobShapeProvider() {
return new HudPaintingUtils.ShapeProvider() {
public Shape createShape(double x, double y, double width, double height) {
return new Ellipse2D.Double(x, y, width, height);
}
};
}
/**
* Cerates a pointy slider thumb:
* <pre>
* +----+
* / \
* + +
* | |
* + +
* \ /
* \/
* </pre>
*/
private static HudPaintingUtils.ShapeProvider createPointedSliderKnobShapeProvider() {
return new HudPaintingUtils.ShapeProvider() {
public Shape createShape(double x, double y, double width, double height) {
float xFloat = (float) x;
float yFloat = (float) y;
float widthFloat = (float) width;
float heightFloat = (float) height;
// draw the thumb shape based on the given height and width.
GeneralPath path = new GeneralPath();
// move in two pixels so that we can curve down to the next point.
path.moveTo(xFloat + 2.0f, yFloat);
// curve down to the second point.
path.curveTo(xFloat + 0.25f, yFloat + 0.25f, xFloat - 0.25f,
yFloat + 2.0f, xFloat, yFloat + 2.0f);
// move straight down to the next point.
path.lineTo(xFloat, yFloat + heightFloat / 1.60f);
// move down and right to form the left half of the pointy section.
path.lineTo(xFloat + widthFloat / 2, yFloat + heightFloat);
// move up and right to form the right half of the pointy section.
path.lineTo(xFloat + widthFloat, yFloat + heightFloat / 1.60f);
// move straight up to the point to curve from.
path.lineTo(xFloat + widthFloat, yFloat + 2.0f);
// curve up and right to the top of the thumb.
path.curveTo(xFloat + widthFloat - 0.25f, yFloat + 2.0f,
xFloat + widthFloat - 0.25f, yFloat + 0.25f,
xFloat + widthFloat - 2.0f, yFloat);
path.closePath();
return path;
}
};
}
}
|