blob: 650ebca8f063236c32c70898602a975a136fd060 [file] [log] [blame]
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.felix.mosgi.managedelements.memoryprobe.tab;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.BoundedRangeModel;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.SliderUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicSliderUI;
public class LogarithmicJSlider extends JSlider {
public LogarithmicJSlider(int min, int max, int value) {
super(min, max, value);
SliderUI ui = new LogSliderUI(this);
this.setUI(ui);
}
public static class LogSliderUI extends BasicSliderUI {
public LogSliderUI(JSlider b) {
super(b);
}
public int xPositionForValue(int value) {
int min = slider.getMinimum();
int max = slider.getMaximum();
int trackLength = trackRect.width;
double valueRange = (double) Math.log(max) - (double) Math.log(min);
double pixelsPerValue = (double) trackLength / valueRange;
int trackLeft = trackRect.x;
int trackRight = trackRect.x + (trackRect.width - 1);
int xPosition;
if (!drawInverted()) {
xPosition = trackLeft;
xPosition += Math.round(pixelsPerValue * ((double) Math.log(value) - Math.log(min)));
} else {
xPosition = trackRight;
xPosition -= Math.round(pixelsPerValue * ((double) Math.log(value) - Math.log(min)));
}
xPosition = Math.max(trackLeft, xPosition);
xPosition = Math.min(trackRight, xPosition);
return xPosition;
}
public int yPositionForValue(int value) {
// TODO GH: Implement to support vertical log sliders
return super.yPositionForValue(value);
}
public int valueForYPosition(int yPos) {
// TODO GH: Implement to support vertical log sliders
return super.valueForYPosition(yPos);
}
public int valueForXPosition(int xPos) {
int value;
final int minValue = slider.getMinimum();
final int maxValue = slider.getMaximum();
final int trackLength = trackRect.width;
final int trackLeft = trackRect.x;
final int trackRight = trackRect.x + (trackRect.width - 1);
if (xPos <= trackLeft) {
value = drawInverted() ? maxValue : minValue;
} else if (xPos >= trackRight) {
value = drawInverted() ? minValue : maxValue;
} else {
int distanceFromTrackLeft = xPos - trackLeft;
double valueRange = (double) Math.log(maxValue) - (double) Math.log(minValue);
//double valuePerPixel = (double)valueRange / (double)trackLength;
//int valueFromTrackLeft =
// (int)Math.round( Math.pow(3.5,(double)distanceFromTrackLeft * (double)valuePerPixel));
int valueFromTrackLeft =
(int)
Math.round(Math.pow(Math.E, Math.log(minValue) + ((((double) distanceFromTrackLeft) * valueRange) / (double) trackLength)));
value = drawInverted() ? maxValue - valueFromTrackLeft :
(int) Math.log(minValue) + valueFromTrackLeft;
}
return value;
}
public void paintTicks(Graphics g) {
Rectangle tickBounds = tickRect;
int i;
int maj, min, max;
int w = tickBounds.width;
int h = tickBounds.height;
int centerEffect, tickHeight;
g.setColor(Color.black);
maj = slider.getMajorTickSpacing();
min = slider.getMinorTickSpacing();
if (slider.getOrientation() == JSlider.HORIZONTAL) {
g.translate(0, tickBounds.y);
int value = slider.getMinimum();
int xPos = 0;
if (slider.getMinorTickSpacing() > 0) {
int majorValue = slider.getMinimum();
while (value <= slider.getMaximum()) {
if (value >= majorValue) {
value = majorValue;
majorValue *= maj;
}
value += (majorValue / 10.0);
xPos = xPositionForValue(value);
paintMinorTickForHorizSlider(g, tickBounds, xPos);
}
}
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 majorValue = slider.getMinimum();
int offset = 0;
if (!slider.getComponentOrientation().isLeftToRight()) {
offset = tickBounds.width - tickBounds.width / 2;
g.translate(offset, 0);
}
while (value <= slider.getMaximum()) {
if (value >= majorValue) {
value = majorValue;
majorValue *= maj;
}
yPos = yPositionForValue(value);
paintMinorTickForVertSlider(g, tickBounds, yPos);
value += (majorValue / 10.0);
}
if (!slider.getComponentOrientation().isLeftToRight()) {
g.translate(-offset, 0);
}
}
if (slider.getMajorTickSpacing() > 0) {
value = slider.getMinimum();
if (!slider.getComponentOrientation().isLeftToRight()) {
g.translate(2, 0);
}
while (value <= slider.getMaximum()) {
yPos = yPositionForValue(value);
paintMajorTickForVertSlider(g, tickBounds, yPos);
value *= slider.getMajorTickSpacing();
}
if (!slider.getComponentOrientation().isLeftToRight()) {
g.translate(-2, 0);
}
}
g.translate(-tickBounds.x, 0);
}
}
}
public Hashtable createStandardLabels(int increment, int start) {
if (start > getMaximum() || start < getMinimum()) {
throw new IllegalArgumentException("Slider label start point out of range.");
}
if (increment <= 0) {
throw new IllegalArgumentException("Label incremement must be > 0");
}
class LabelHashtable extends Hashtable implements PropertyChangeListener {
int increment = 0;
int start = 0;
boolean startAtMin = false;
public LabelHashtable(int increment, int start) {
super();
this.increment = increment;
this.start = start;
startAtMin = start == getMinimum();
createLabels(this, increment, start);
}
public void propertyChange(PropertyChangeEvent e) {
if (e.getPropertyName().equals("minimum") && startAtMin) {
start = getMinimum();
}
if (e.getPropertyName().equals("minimum") ||
e.getPropertyName().equals("maximum")) {
Enumeration keys = getLabelTable().keys();
Object key = null;
Hashtable hashtable = new Hashtable();
// Save the labels that were added by the developer
while (keys.hasMoreElements()) {
key = keys.nextElement();
Object value = getLabelTable().get(key);
if (!(value instanceof LabelUIResource)) {
hashtable.put(key, value);
}
}
clear();
createLabels(this, increment, start);
// Add the saved labels
keys = hashtable.keys();
while (keys.hasMoreElements()) {
key = keys.nextElement();
put(key, hashtable.get(key));
}
((JSlider) e.getSource()).setLabelTable(this);
}
}
}
LabelHashtable table = new LabelHashtable(increment, start);
if (getLabelTable() != null && (getLabelTable() instanceof PropertyChangeListener)) {
removePropertyChangeListener((PropertyChangeListener) getLabelTable());
}
addPropertyChangeListener(table);
return table;
}
/**
* This method creates the table of labels that are used to label major ticks
* on the slider.
* @param table
* @param increment
* @param start
*/
protected void createLabels(Hashtable table, int increment, int start) {
for (int labelIndex = start; labelIndex <= getMaximum(); labelIndex *= increment) {
table.put(new Integer(labelIndex), new LabelUIResource("" + labelIndex, JLabel.CENTER));
}
}
protected static class LabelUIResource extends JLabel implements UIResource {
public LabelUIResource(String text, int alignment) {
super(text, alignment);
setName("Slider.label");
}
}
}