/* * @(#)BasicNewRangeSliderUI.java 7/3/2010 * * Copyright 2002 - 2010 JIDE Software Inc. All rights reserved. */ package com.jidesoft.plaf.basic; import com.jidesoft.swing.RangeSlider; import javax.swing.*; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicSliderUI; import java.awt.*; import java.awt.event.MouseEvent; import java.lang.reflect.Field; /** * BasicRangeSliderUI implementation */ public class BasicRangeSliderUI extends BasicSliderUI { public BasicRangeSliderUI(JSlider slider) { super(slider); } // ******************************** // Create PLAF // ******************************** public static ComponentUI createUI(JComponent slider) { return new BasicRangeSliderUI((JSlider) slider); } @Override public void paint(Graphics g, JComponent c) { second = false; super.paint(g, c); Rectangle clip = g.getClipBounds(); second = true; Point p = adjustThumbForHighValue(); if (clip.intersects(thumbRect)) { paintThumb(g); } restoreThumbForLowValue(p); second = false; } protected void restoreThumbForLowValue(Point p) { thumbRect.x = p.x; thumbRect.y = p.y; } protected Point adjustThumbForHighValue() { Point p = thumbRect.getLocation(); if (slider.getOrientation() == JSlider.HORIZONTAL) { int valuePosition = xPositionForValue(((RangeSlider) slider).getHighValue()); thumbRect.x = valuePosition - (thumbRect.width / 2); } else { int valuePosition = yPositionForValue(((RangeSlider) slider).getHighValue()); thumbRect.y = valuePosition - (thumbRect.height / 2); } return p; } protected void adjustSnapHighValue() { int sliderValue = ((RangeSlider) slider).getHighValue(); int snappedValue = sliderValue; int majorTickSpacing = slider.getMajorTickSpacing(); int minorTickSpacing = slider.getMinorTickSpacing(); int tickSpacing = 0; if (minorTickSpacing > 0) { tickSpacing = minorTickSpacing; } else if (majorTickSpacing > 0) { tickSpacing = majorTickSpacing; } if (tickSpacing != 0) { // If it's not on a tick, change the value if ((sliderValue - slider.getMinimum()) % tickSpacing != 0) { float temp = (float) (sliderValue - slider.getMinimum()) / (float) tickSpacing; int whichTick = Math.round(temp); snappedValue = slider.getMinimum() + (whichTick * tickSpacing); } if (snappedValue != sliderValue) { ((RangeSlider) slider).setHighValue(snappedValue); } } } @Override protected void calculateThumbLocation() { if (slider.getSnapToTicks()) { adjustSnapHighValue(); } super.calculateThumbLocation(); } @Override protected TrackListener createTrackListener(JSlider slider) { return new RangeTrackListener(super.createTrackListener(slider)); } protected class RangeTrackListener extends TrackListener { int handle; int handleOffset; int mouseStartLocation; TrackListener _listener; public RangeTrackListener(TrackListener listener) { _listener = listener; } /** * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent) */ @Override public void mousePressed(MouseEvent e) { if (!slider.isEnabled()) { return; } if (slider.isRequestFocusEnabled()) { slider.requestFocus(); } handle = getMouseHandle(e.getX(), e.getY()); setMousePressed(handle); if (handle == MOUSE_HANDLE_MAX || handle == MOUSE_HANDLE_MIN || handle == MOUSE_HANDLE_MIDDLE || handle == MOUSE_HANDLE_BOTH) { handleOffset = (slider.getOrientation() == JSlider.VERTICAL) ? e.getY() - yPositionForValue(((RangeSlider) slider).getLowValue()) : e.getX() - xPositionForValue(((RangeSlider) slider).getLowValue()); mouseStartLocation = (slider.getOrientation() == JSlider.VERTICAL) ? e.getY() : e.getX(); slider.getModel().setValueIsAdjusting(true); } else if (handle == MOUSE_HANDLE_LOWER || handle == MOUSE_HANDLE_UPPER) { _listener.mousePressed(e); slider.putClientProperty(RangeSlider.CLIENT_PROPERTY_MOUSE_POSITION, null); } } /** * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent) */ @Override public void mouseDragged(MouseEvent e) { if (!slider.isEnabled()) { return; } int newLocation = (slider.getOrientation() == JSlider.VERTICAL) ? e.getY() : e.getX(); int newValue = (slider.getOrientation() == JSlider.VERTICAL) ? valueForYPosition(newLocation) : valueForXPosition(newLocation); if (newValue < slider.getModel().getMinimum()) { newValue = slider.getModel().getMinimum(); } if (newValue > slider.getModel().getMaximum()) { newValue = slider.getModel().getMaximum(); } if (handle == MOUSE_HANDLE_BOTH) { if ((newLocation - mouseStartLocation) >= 1) { handle = MOUSE_HANDLE_MAX; } else if ((newLocation - mouseStartLocation) <= -1) { handle = MOUSE_HANDLE_MIN; } else { return; } } RangeSlider rangeSlider = (RangeSlider) slider; switch (handle) { case MOUSE_HANDLE_MIN: rangeSlider.setLowValue(Math.min(newValue, rangeSlider.getHighValue())); break; case MOUSE_HANDLE_MAX: rangeSlider.setHighValue(Math.max(rangeSlider.getLowValue(), newValue)); break; case MOUSE_HANDLE_MIDDLE: if (((RangeSlider) slider).isRangeDraggable()) { int delta = (slider.getOrientation() == JSlider.VERTICAL) ? valueForYPosition(newLocation - handleOffset) - rangeSlider.getLowValue() : valueForXPosition(newLocation - handleOffset) - rangeSlider.getLowValue(); if ((delta < 0) && ((rangeSlider.getLowValue() + delta) < rangeSlider.getMinimum())) { delta = rangeSlider.getMinimum() - rangeSlider.getLowValue(); } if ((delta > 0) && ((rangeSlider.getHighValue() + delta) > rangeSlider.getMaximum())) { delta = rangeSlider.getMaximum() - rangeSlider.getHighValue(); } if (delta != 0) { rangeSlider.setLowValue(rangeSlider.getLowValue() + delta); rangeSlider.setHighValue(rangeSlider.getHighValue() + delta); } } break; } } /** * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) */ @Override public void mouseReleased(MouseEvent e) { slider.getModel().setValueIsAdjusting(false); setMouseReleased(handle); _listener.mouseReleased(e); } private void setCursor(int c) { Cursor cursor = Cursor.getPredefinedCursor(c); if (slider.getCursor() != cursor) { slider.setCursor(cursor); } } /** * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent) */ @Override public void mouseMoved(MouseEvent e) { if (!slider.isEnabled()) { return; } int handle = getMouseHandle(e.getX(), e.getY()); setMouseRollover(handle); switch (handle) { case MOUSE_HANDLE_MIN: setCursor(Cursor.DEFAULT_CURSOR); break; case MOUSE_HANDLE_MAX: setCursor(Cursor.DEFAULT_CURSOR); break; case MOUSE_HANDLE_MIDDLE: case MOUSE_HANDLE_BOTH: if (slider instanceof RangeSlider && ((RangeSlider) slider).isRangeDraggable()) { setCursor(Cursor.MOVE_CURSOR); } else { setCursor(Cursor.DEFAULT_CURSOR); } break; case MOUSE_HANDLE_NONE: default: setCursor(Cursor.DEFAULT_CURSOR); break; } } /** * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) */ @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { slider.getModel().setValue(slider.getModel().getMinimum()); slider.getModel().setExtent(slider.getModel().getMaximum() - slider.getModel().getMinimum()); slider.repaint(); } } /** * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent) */ @Override public void mouseEntered(MouseEvent e) { hover = true; slider.repaint(); } /** * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent) */ @Override public void mouseExited(MouseEvent e) { hover = false; slider.repaint(); setCursor(Cursor.DEFAULT_CURSOR); } } protected static final int MOUSE_HANDLE_NONE = 0; protected static final int MOUSE_HANDLE_MIN = 1; protected static final int MOUSE_HANDLE_MAX = 2; protected static final int MOUSE_HANDLE_MIDDLE = 4; protected static final int MOUSE_HANDLE_LOWER = 5; protected static final int MOUSE_HANDLE_UPPER = 6; protected static final int MOUSE_HANDLE_BOTH = 7; protected int getMouseHandle(int x, int y) { Rectangle rect = trackRect; slider.putClientProperty(RangeSlider.CLIENT_PROPERTY_MOUSE_POSITION, null); boolean inMin = false; boolean inMax = false; if (thumbRect.contains(x, y)) { inMin = true; } Point p = adjustThumbForHighValue(); if (thumbRect.contains(x, y)) { inMax = true; } restoreThumbForLowValue(p); if (inMin && inMax) { return MOUSE_HANDLE_BOTH; } else if (inMin) { return MOUSE_HANDLE_MIN; } else if (inMax) { return MOUSE_HANDLE_MAX; } if (slider.getOrientation() == JSlider.VERTICAL) { int minY = yPositionForValue(((RangeSlider) slider).getLowValue()); int maxY = yPositionForValue(((RangeSlider) slider).getHighValue()); Rectangle midRect = new Rectangle(rect.x, Math.min(minY, maxY) + thumbRect.height / 2, rect.width, Math.abs(maxY - minY) - thumbRect.height); if (midRect.contains(x, y)) { return MOUSE_HANDLE_MIDDLE; } int sy = rect.y + Math.max(minY, maxY) + thumbRect.height / 2; Rectangle lowerRect = new Rectangle(rect.x, sy, rect.width, rect.y + rect.height - sy); if (lowerRect.contains(x, y)) { slider.putClientProperty(RangeSlider.CLIENT_PROPERTY_MOUSE_POSITION, true); return MOUSE_HANDLE_LOWER; } Rectangle upperRect = new Rectangle(rect.x, rect.y, rect.width, Math.min(maxY, minY) - thumbRect.height / 2); if (upperRect.contains(x, y)) { slider.putClientProperty(RangeSlider.CLIENT_PROPERTY_MOUSE_POSITION, false); return MOUSE_HANDLE_UPPER; } return MOUSE_HANDLE_NONE; } else { int minX = xPositionForValue(((RangeSlider) slider).getLowValue()); int maxX = xPositionForValue(((RangeSlider) slider).getHighValue()); Rectangle midRect = new Rectangle(Math.min(minX, maxX) + thumbRect.width / 2, rect.y, Math.abs(maxX - minX) - thumbRect.width, rect.height); if (midRect.contains(x, y)) { return MOUSE_HANDLE_MIDDLE; } Rectangle lowerRect = new Rectangle(rect.x, rect.y, Math.min(minX, maxX) - thumbRect.width / 2 - rect.x, rect.height); if (lowerRect.contains(x, y)) { slider.putClientProperty(RangeSlider.CLIENT_PROPERTY_MOUSE_POSITION, true); return MOUSE_HANDLE_LOWER; } int sx = rect.x + Math.abs(maxX - minX) + thumbRect.width / 2; Rectangle upperRect = new Rectangle(sx, rect.y, rect.width - sx, rect.height); if (upperRect.contains(x, y)) { slider.putClientProperty(RangeSlider.CLIENT_PROPERTY_MOUSE_POSITION, false); return MOUSE_HANDLE_UPPER; } return MOUSE_HANDLE_NONE; } } protected boolean hover; protected boolean second; protected boolean rollover1; protected boolean pressed1; protected boolean rollover2; protected boolean pressed2; @Override public void paintThumb(Graphics g) { try { Field field = getClass().getSuperclass().getDeclaredField("rollover"); field.setAccessible(true); field.set(this, second ? rollover2 : rollover1); field = getClass().getSuperclass().getDeclaredField("pressed"); field.setAccessible(true); field.set(this, second ? pressed2 : pressed1); } catch (NoSuchFieldException e) { // e.printStackTrace(); } catch (IllegalAccessException e) { // e.printStackTrace(); } super.paintThumb(g); } protected void setMouseRollover(int handle) { switch (handle) { case MOUSE_HANDLE_MIN: { rollover1 = true; rollover2 = false; } break; case MOUSE_HANDLE_MAX: { rollover2 = true; rollover1 = false; } break; case MOUSE_HANDLE_MIDDLE: case MOUSE_HANDLE_BOTH: { rollover1 = true; rollover2 = true; } break; case MOUSE_HANDLE_NONE: rollover1 = false; rollover2 = false; break; } slider.repaint(thumbRect); Point p = adjustThumbForHighValue(); slider.repaint(thumbRect); restoreThumbForLowValue(p); } protected void setMousePressed(int handle) { switch (handle) { case MOUSE_HANDLE_MIN: { pressed1 = true; pressed2 = false; } break; case MOUSE_HANDLE_MAX: { pressed2 = true; pressed1 = false; } break; case MOUSE_HANDLE_MIDDLE: case MOUSE_HANDLE_BOTH: { pressed1 = true; pressed2 = true; } break; case MOUSE_HANDLE_NONE: pressed1 = false; pressed2 = false; break; } slider.repaint(thumbRect); Point p = adjustThumbForHighValue(); slider.repaint(thumbRect); restoreThumbForLowValue(p); } @SuppressWarnings({"UnusedDeclaration"}) protected void setMouseReleased(int handle) { pressed1 = false; pressed2 = false; slider.repaint(thumbRect); Point p = adjustThumbForHighValue(); slider.repaint(thumbRect); restoreThumbForLowValue(p); } @Override public void scrollByBlock(int direction) { synchronized (slider) { int oldValue; Object clientProperty = slider.getClientProperty(RangeSlider.CLIENT_PROPERTY_MOUSE_POSITION); if (clientProperty == null) { oldValue = slider.getValue(); } else if (Boolean.TRUE.equals(clientProperty)) { oldValue = ((RangeSlider) slider).getLowValue(); } else { oldValue = ((RangeSlider) slider).getHighValue(); } int blockIncrement = (slider.getMaximum() - slider.getMinimum()) / 10; if (blockIncrement <= 0 && slider.getMaximum() > slider.getMinimum()) { blockIncrement = 1; } int delta = blockIncrement * ((direction > 0) ? POSITIVE_SCROLL : NEGATIVE_SCROLL); slider.putClientProperty(RangeSlider.CLIENT_PROPERTY_ADJUST_ACTION, "scrollByBlock"); if (clientProperty == null) { slider.setValue(Math.max(Math.min(oldValue + delta, slider.getMaximum()), slider.getMinimum())); } else if (Boolean.TRUE.equals(clientProperty)) { ((RangeSlider) slider).setLowValue(Math.max(Math.min(oldValue + delta, slider.getMaximum()), slider.getMinimum())); } else { ((RangeSlider) slider).setHighValue(Math.max(Math.min(oldValue + delta, slider.getMaximum()), slider.getMinimum())); } slider.putClientProperty(RangeSlider.CLIENT_PROPERTY_ADJUST_ACTION, null); } } @Override public void scrollByUnit(int direction) { synchronized (slider) { int oldValue; Object clientProperty = slider.getClientProperty(RangeSlider.CLIENT_PROPERTY_MOUSE_POSITION); if (clientProperty == null) { oldValue = slider.getValue(); } else if (Boolean.TRUE.equals(clientProperty)) { oldValue = ((RangeSlider) slider).getLowValue(); } else { oldValue = ((RangeSlider) slider).getHighValue(); } int delta = 1 * ((direction > 0) ? POSITIVE_SCROLL : NEGATIVE_SCROLL); slider.putClientProperty(RangeSlider.CLIENT_PROPERTY_ADJUST_ACTION, "scrollByUnit"); if (clientProperty == null) { slider.setValue(Math.max(Math.min(oldValue + delta, slider.getMaximum()), slider.getMinimum())); } else if (Boolean.TRUE.equals(clientProperty)) { ((RangeSlider) slider).setLowValue(Math.max(Math.min(oldValue + delta, slider.getMaximum()), slider.getMinimum())); } else { ((RangeSlider) slider).setHighValue(Math.max(Math.min(oldValue + delta, slider.getMaximum()), slider.getMinimum())); } slider.putClientProperty(RangeSlider.CLIENT_PROPERTY_ADJUST_ACTION, null); } } }