package prefuse.data.query; import javax.swing.DefaultBoundedRangeModel; import prefuse.util.TypeLib; import prefuse.util.ui.ValuedRangeModel; /** * Range model for numerical data. Designed to support range-based dynamic * queries. * * @author <a href="http://jheer.org">jeffrey heer</a> */ public class NumberRangeModel extends DefaultBoundedRangeModel implements ValuedRangeModel { protected Class m_type; protected Number m_min, m_max, m_lo, m_hi; // ------------------------------------------------------------------------ /** * Create a new NumberRangeModel for the given range. * @param lo the low value of the selected range * @param hi the high value of the selected range * @param min the minimum value allowed for ranges * @param max the maximum value allowed for ranges */ public NumberRangeModel(int lo, int hi, int min, int max) { this(new Integer(lo), new Integer(hi), new Integer(min), new Integer(hi)); } /** * Create a new NumberRangeModel for the given range. * @param lo the low value of the selected range * @param hi the high value of the selected range * @param min the minimum value allowed for ranges * @param max the maximum value allowed for ranges */ public NumberRangeModel(long lo, long hi, long min, long max) { this(new Long(lo), new Long(hi), new Long(min), new Long(max)); } /** * Create a new NumberRangeModel for the given range. * @param lo the low value of the selected range * @param hi the high value of the selected range * @param min the minimum value allowed for ranges * @param max the maximum value allowed for ranges */ public NumberRangeModel(float lo, float hi, float min, float max) { this(new Float(lo), new Float(hi), new Float(min), new Float(max)); } /** * Create a new NumberRangeModel for the given range. * @param lo the low value of the selected range * @param hi the high value of the selected range * @param min the minimum value allowed for ranges * @param max the maximum value allowed for ranges */ public NumberRangeModel(double lo, double hi, double min, double max) { this(new Double(lo), new Double(hi), new Double(min), new Double(max)); } /** * Create a new NumberRangeModel for the given range. * @param lo the low value of the selected range * @param hi the high value of the selected range * @param min the minimum value allowed for ranges * @param max the maximum value allowed for ranges */ public NumberRangeModel(Number lo, Number hi, Number min, Number max) { m_type = TypeLib.getPrimitiveType(min.getClass()); setValueRange(lo, hi, min, max); } // ------------------------------------------------------------------------ /** * Update the range settings based on current values. */ protected void updateRange() { if ( m_type == int.class ) { setRange(m_lo.intValue(), m_hi.intValue()-m_lo.intValue(), m_min.intValue(), m_max.intValue()); } else if ( m_type == long.class ) { long range = m_max.longValue() - m_min.longValue(); if (range == 0) { setRange(0, 0, 0, 0); } else { long lo = m_lo.longValue() - m_min.longValue(); long hi = m_hi.longValue() - m_min.longValue(); int v = 10000 * (int)( lo / range ); int e = 10000 * (int)( hi / range ) - v; setRange(v, e, 0, 10000); } } else { double range = m_max.doubleValue() - m_min.doubleValue(); if (range == 0) { setRange(0, 0, 0, 0); } else { double lo = m_lo.doubleValue() - m_min.doubleValue(); double hi = m_hi.doubleValue() - m_min.doubleValue(); int v = 10000 * (int)( lo / range ); int e = 10000 * (int)( hi / range ) - v; setRange(v, e, 0, 10000); } } } /** * Set the range settings in the pixel-space coordinates. */ protected void setRange(int val, int ext, int min, int max) { super.setRangeProperties(val, ext, min, max, false); } /** * @see javax.swing.BoundedRangeModel#setRangeProperties(int, int, int, int, boolean) */ public void setRangeProperties(int val, int extent, int min, int max, boolean adj) { if ( min!=getMinimum() || max!= getMaximum() ) { throw new IllegalArgumentException("Can not change min or max."); } m_lo = null; m_hi = null; super.setRangeProperties(val, extent, min, max, adj); } /** * Set the range model's backing values. * @param lo the low value of the selected range * @param hi the high value of the selected range * @param min the minimum value allowed for ranges * @param max the maximum value allowed for ranges */ public void setValueRange(Number lo, Number hi, Number min, Number max) { m_lo = lo; m_hi = hi; m_min = min; m_max = max; updateRange(); } /** * Set the range model's backing values. * @param lo the low value of the selected range * @param hi the high value of the selected range * @param min the minimum value allowed for ranges * @param max the maximum value allowed for ranges */ public void setValueRange(double lo, double hi, double min, double max) { m_lo = new Double(lo); m_hi = new Double(hi); m_min = new Double(min); m_max = new Double(max); updateRange(); } /** * Set the range model's backing values. * @param lo the low value of the selected range * @param hi the high value of the selected range * @param min the minimum value allowed for ranges * @param max the maximum value allowed for ranges */ public void setValueRange(int lo, int hi, int min, int max) { m_lo = new Integer(lo); m_hi = new Integer(hi); m_min = new Integer(min); m_max = new Integer(max); updateRange(); } /** * Set the range model's backing values. * @param lo the low value of the selected range * @param hi the high value of the selected range * @param min the minimum value allowed for ranges * @param max the maximum value allowed for ranges */ public void setValueRange(long lo, long hi, long min, long max) { m_lo = new Long(lo); m_hi = new Long(hi); m_min = new Long(min); m_max = new Long(max); updateRange(); } /** * @see prefuse.util.ui.ValuedRangeModel#getMinValue() */ public Object getMinValue() { return m_min; } /** * Set the minimum range value. * @param n the minimum range value. */ public void setMinValue(Number n) { setValueRange((Number)getLowValue(), (Number)getHighValue(), n, m_max); } /** * @see prefuse.util.ui.ValuedRangeModel#getMaxValue() */ public Object getMaxValue() { return m_max; } /** * Set the maximum range value. * @param n the maximum range value. */ public void setMaxValue(Number n) { setValueRange((Number)getLowValue(), (Number)getHighValue(), m_min, n); } /** * @see prefuse.util.ui.ValuedRangeModel#getLowValue() */ public Object getLowValue() { if ( m_lo == null ) m_lo = (Number)value(getValue()); return m_lo; } /** * Set the lowest selected range value. * @param n the low value of the selected range. */ public void setLowValue(Number n) { setValueRange(n, (Number)getHighValue(), m_min, m_max); } /** * @see prefuse.util.ui.ValuedRangeModel#getHighValue() */ public Object getHighValue() { if ( m_hi == null ) m_hi = (Number)value(getValue()+getExtent()); return m_hi; } /** * Set the highest selected range value. * @param n the high value of the selected range. */ public void setHighValue(Number n) { setValueRange((Number)getLowValue(), n, m_min, m_max); } protected Object value(int val) { int min = getMinimum(); int max = getMaximum(); if ( m_type == double.class || m_type == float.class ) { double f = (val-min)/(double)(max-min); double m = m_min.doubleValue(); double v = m + f*(m_max.doubleValue()-m); return (m_type==float.class ? (Number)new Float((float)v) : new Double(v)); } else if ( m_type == long.class ) { long m = m_min.longValue(); long v = m + (val-min)*(m_max.longValue()-m)/(max-min); return new Long(v); } else { return new Integer(val); } } /** * Not supported, throws an exception. * @throws UnsupportedOperationException * @see javax.swing.BoundedRangeModel#setMinimum(int) */ public void setMinimum(int min) { throw new UnsupportedOperationException(); } /** * Not supported, throws an exception. * @throws UnsupportedOperationException * @see javax.swing.BoundedRangeModel#setMaximum(int) */ public void setMaximum(int max) { throw new UnsupportedOperationException(); } /** * @see javax.swing.BoundedRangeModel#setValue(int) */ public void setValue(int val) { m_lo = null; super.setValue(val); } /** * @see javax.swing.BoundedRangeModel#setExtent(int) */ public void setExtent(int extent) { m_hi = null; super.setExtent(extent); } } // end of class NumberRangeModel