/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Liquid Look and Feel *
* *
* Author, Miroslav Lazarevic *
* *
* For licensing information and credits, please refer to the *
* comment in file com.birosoft.liquid.LiquidLookAndFeel *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package com.birosoft.liquid;
import com.birosoft.liquid.skin.Skin;
import com.birosoft.liquid.skin.SkinSimpleButtonIndexModel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.JComponent;
import javax.swing.JSlider;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSliderUI;
public class LiquidSliderUI extends BasicSliderUI {
/** the skin for the horizontal thumb*/
private static Skin skinThumbHoriz;
/** the skin for the vertical thumb*/
private static Skin skinThumbVert;
/** the skin for the horizontal slider*/
private static Skin skinHorizSlider;
/** the skin for the vertical slider*/
private static Skin skinVertSlider;
private Skin skinSlider;
private SkinSimpleButtonIndexModel skinIndexModel = new SkinSimpleButtonIndexModel();
protected boolean isRollover = false;
protected boolean wasRollover = false;
protected boolean isDragging = false;
protected TrackListener trackListener;
public LiquidSliderUI() {
super(null);
}
protected TrackListener createTrackListener(JSlider slider) {
return new MyTrackListener();
}
protected Dimension getThumbSize() {
Dimension size = getSkinThumb().getSize();
return size;
}
public void paintThumb(Graphics g) {
Rectangle knobBounds = thumbRect;
int index = skinIndexModel.getIndexForState(slider.isEnabled(),
isRollover, isDragging);
getSkinThumb().drawCentered(g, index, knobBounds.x, knobBounds.y,
knobBounds.width, knobBounds.height);
}
public static ComponentUI createUI(JComponent c) {
return new LiquidSliderUI();
}
/**
* Returns the shorter dimension of the track.
*/
protected int getTrackWidth() {
// This strange calculation is here to keep the
// track in proportion to the thumb.
final double kIdealTrackWidth = 7.0;
final double kIdealThumbHeight = 16.0;
final double kWidthScalar = kIdealTrackWidth / kIdealThumbHeight;
if (slider.getOrientation() == JSlider.HORIZONTAL) {
return (int) (kWidthScalar * thumbRect.height);
} else {
return (int) (kWidthScalar * thumbRect.width);
}
}
protected int getThumbOverhang() {
if (slider.getOrientation() == JSlider.VERTICAL) {
return (int) (getThumbSize().getWidth() - getTrackWidth()) / 2;
} else {
return (int) (getThumbSize().getHeight() - getTrackWidth()) / 2;
}
}
public void paint(Graphics g, JComponent c) {
c.setOpaque(false);
g.setColor(new Color(0, 0, 0, 0));
g.fillRect(0, 0, c.getWidth(), c.getHeight());
super.paint(g, c);
}
public void paintTicks(Graphics g) {
Rectangle tickBounds = tickRect;
boolean leftToRight = slider.getComponentOrientation().isLeftToRight();
g.setColor(new Color(0, 0, 0, 0));
g.fillRect(tickBounds.x, tickBounds.y, tickBounds.width,
tickBounds.height);
g.setColor(Color.black);
if (slider.getOrientation() == JSlider.HORIZONTAL) {
g.translate(0, tickBounds.y);
int value = slider.getMinimum();
int xPos = 0;
if (slider.getMinorTickSpacing() > 0) {
while (value <= slider.getMaximum()) {
xPos = xPositionForValue(value);
paintMinorTickForHorizSlider(g, tickBounds, xPos);
value += slider.getMinorTickSpacing();
}
}
if (slider.getMajorTickSpacing() > 0) {
value = slider.getMinimum();
while (value <= slider.getMaximum()) {
xPos = xPositionForValue(value);
paintMajorTickForHorizSlider(g, tickBounds, xPos);
value += slider.getMajorTickSpacing();
}
}
g.translate(0, -tickBounds.y);
} else {
g.translate(tickBounds.x, 0);
int value = slider.getMinimum();
int yPos = 0;
if (slider.getMinorTickSpacing() > 0) {
int offset = 0;
if (!leftToRight) {
offset = tickBounds.width - (tickBounds.width / 2);
g.translate(offset, 0);
}
while (value <= slider.getMaximum()) {
yPos = yPositionForValue(value);
paintMinorTickForVertSlider(g, tickBounds, yPos);
value += slider.getMinorTickSpacing();
}
if (!leftToRight) {
g.translate(-offset, 0);
}
}
if (slider.getMajorTickSpacing() > 0) {
value = slider.getMinimum();
if (!leftToRight) {
g.translate(2, 0);
}
while (value <= slider.getMaximum()) {
yPos = yPositionForValue(value);
paintMajorTickForVertSlider(g, tickBounds, yPos);
value += slider.getMajorTickSpacing();
}
if (!leftToRight) {
g.translate(-2, 0);
}
}
g.translate(-tickBounds.x, 0);
}
}
public void paintTrack(Graphics g) {
boolean leftToRight = slider.getComponentOrientation().isLeftToRight();
g.translate(trackRect.x, trackRect.y);
int trackLeft = 0;
int trackTop = 0;
int trackRight = 0;
int trackBottom = 0;
// Draw the track
if (slider.getOrientation() == JSlider.HORIZONTAL) {
trackBottom = (trackRect.height - 1) - getThumbOverhang();
trackTop = trackBottom - (getTrackWidth() - 1);
trackRight = trackRect.width - 1;
int h = (trackBottom - trackTop - getSkinHorizSlider().getVsize()) / 2;
getSkinHorizSlider().draw(g, 0, trackLeft, trackTop + h,
trackRight - trackLeft, getSkinHorizSlider().getVsize());
} else {
if (leftToRight) {
trackLeft = (trackRect.width - getThumbOverhang()) -
getTrackWidth();
trackRight = (trackRect.width - getThumbOverhang()) - 1;
} else {
trackLeft = getThumbOverhang();
trackRight = (getThumbOverhang() + getTrackWidth()) - 1;
}
trackBottom = trackRect.height - 1;
int w = (trackRight - trackLeft - getSkinVertSlider().getHsize()) / 2;
getSkinVertSlider().draw(g, 0, trackLeft + w, trackTop,
getSkinVertSlider().getHsize(), trackBottom - trackTop);
}
g.translate(-trackRect.x, -trackRect.y);
}
protected void paintMinorTickForHorizSlider(Graphics g,
Rectangle tickBounds, int x) {
g.setColor(LiquidLookAndFeel.getDarkControl());
g.drawLine(x, 0, x, (tickBounds.height / 2) - 1);
}
protected void paintMajorTickForHorizSlider(Graphics g,
Rectangle tickBounds, int x) {
g.setColor(LiquidLookAndFeel.getDarkControl());
g.drawLine(x, 0, x, tickBounds.height - 2);
}
protected void paintMinorTickForVertSlider(Graphics g,
Rectangle tickBounds, int y) {
g.setColor(LiquidLookAndFeel.getDarkControl());
g.drawLine(0, y, (tickBounds.width / 2) - 1, y);
}
protected void paintMajorTickForVertSlider(Graphics g,
Rectangle tickBounds, int y) {
g.setColor(LiquidLookAndFeel.getDarkControl());
g.drawLine(0, y, tickBounds.width - 2, y);
}
/**
* Returns the skinHorizSlider.
* @return SkinGenericButton
*/
public static Skin getSkinHorizSlider() {
if (skinHorizSlider == null) {
skinHorizSlider = new Skin("sliderhorizbackground.png", 1, 6, 0, 6,
0);
}
return skinHorizSlider;
}
/**
* Returns the skinThumbHoriz.
* @return SkinCenteredButton
*/
public static Skin getSkinThumbHoriz() {
if (skinThumbHoriz == null) {
skinThumbHoriz = new Skin("sliderhoriz.png", 4, 0);
}
return skinThumbHoriz;
}
/**
* Returns the skinThumbVert.
* @return SkinCenteredButton
*/
public static Skin getSkinThumbVert() {
if (skinThumbVert == null) {
skinThumbVert = new Skin("slidervert.png", 4, 0);
}
return skinThumbVert;
}
/**
* Returns the skinVertSlider.
* @return SkinGenericButton
*/
public static Skin getSkinVertSlider() {
if (skinVertSlider == null) {
skinVertSlider = new Skin("slidervertbackground.png", 1, 0, 6, 0, 6);
}
return skinVertSlider;
}
/**
* Returns the skinSlider.
* @return Skin
*/
public Skin getSkinThumb() {
if (skinSlider == null) {
skinSlider = (slider.getOrientation() == JSlider.HORIZONTAL)
? getSkinThumbHoriz() : getSkinThumbVert();
}
return skinSlider;
}
/**
* This TrackListener extends the BasicSliderUI.TrackListener such that
* rollover and dragging state can be tracked.
*/
class MyTrackListener extends BasicSliderUI.TrackListener {
public void mouseReleased(MouseEvent e) {
super.mouseReleased(e);
isDragging = false;
slider.repaint();
}
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
if (thumbRect.contains(e.getX(), e.getY())) {
isDragging = true;
}
slider.repaint();
}
public void mouseEntered(MouseEvent e) {
isRollover = false;
wasRollover = false;
if (thumbRect.contains(e.getX(), e.getY())) {
isRollover = true;
}
}
public void mouseExited(MouseEvent e) {
isRollover = false;
if (isRollover != wasRollover) {
slider.repaint();
wasRollover = isRollover;
}
}
public void mouseDragged(MouseEvent e) {
if (thumbRect.contains(e.getX(), e.getY())) {
isRollover = true;
}
super.mouseDragged(e);
}
public void mouseMoved(MouseEvent e) {
if (thumbRect.contains(e.getX(), e.getY())) {
isRollover = true;
if (isRollover != wasRollover) {
slider.repaint();
wasRollover = isRollover;
}
} else {
isRollover = false;
if (isRollover != wasRollover) {
slider.repaint();
wasRollover = isRollover;
}
}
}
}
}