axislabellayout.java

来自「用applet实现很多应用小程序」· Java 代码 · 共 598 行 · 第 1/2 页

JAVA
598
字号
package prefuse.action.layout;

import java.awt.geom.Rectangle2D;
import java.text.NumberFormat;
import java.util.Iterator;
import java.util.logging.Logger;

import prefuse.Constants;
import prefuse.data.Schema;
import prefuse.data.query.ObjectRangeModel;
import prefuse.data.tuple.TupleSet;
import prefuse.data.util.Index;
import prefuse.util.MathLib;
import prefuse.util.PrefuseLib;
import prefuse.util.ui.ValuedRangeModel;
import prefuse.visual.VisualItem;
import prefuse.visual.VisualTable;

/**
 * Layout Action that positions axis grid lines and labels for a given
 * range model.
 * 
 * @author <a href="http://jheer.org">jeffrey heer</a>
 */
public class AxisLabelLayout extends Layout {

    public static final String FRAC = "frac";
    public static final String LABEL = "_label";
    public static final String VALUE = "_value";
    
    private AxisLayout m_layout; // pointer to matching layout, if any
    private ValuedRangeModel m_model;
    private double m_lo, m_hi, m_prevlo, m_prevhi;
    
    private NumberFormat m_nf = NumberFormat.getInstance();
    private int m_axis;
    private boolean m_asc = true;
    private int m_scale = Constants.LINEAR_SCALE;
    
    private double m_spacing; // desired spacing between axis labels
    
    /**
     * Create a new AxisLabelLayout layout.
     * @param group the data group of the axis lines and labels
     * @param axis the axis type, either {@link prefuse.Constants#X_AXIS}
     * or {@link prefuse.Constants#Y_AXIS}.
     * @param values the range model that defines the span of the axis
     */
    public AxisLabelLayout(String group, int axis, ValuedRangeModel values)
    {
        this(group, axis, values, null);
    }
    
    /**
     * Create a new AxisLabelLayout layout.
     * @param group the data group of the axis lines and labels
     * @param axis the axis type, either {@link prefuse.Constants#X_AXIS}
     * or {@link prefuse.Constants#Y_AXIS}.
     * @param values the range model that defines the span of the axis
     * @param bounds the layout bounds within which to place the axis marks
     */
    public AxisLabelLayout(String group, int axis, ValuedRangeModel values,
            Rectangle2D bounds)
    {
        super(group);
        if ( bounds != null )
            setLayoutBounds(bounds);
        m_model = values;
        m_axis = axis;
        m_spacing = 50;
    }
    
    /**
     * Create a new AxisLabelLayout layout.
     * @param group the data group of the axis lines and labels
     * @param layout an {@link AxisLayout} instance to model this layout after.
     * The axis type and range model of the provided instance will be used.
     */
    public AxisLabelLayout(String group, AxisLayout layout) {
        this(group, layout, null, 50);
    }
    
    /**
     * Create a new AxisLabelLayout layout.
     * @param group the data group of the axis lines and labels
     * @param layout an {@link AxisLayout} instance to model this layout after.
     * The axis type and range model of the provided instance will be used.
     * @param bounds the layout bounds within which to place the axis marks
     */
    public AxisLabelLayout(String group, AxisLayout layout, Rectangle2D bounds) {
        this(group, layout, bounds, 50);
    }

    /**
     * Create a new AxisLabelLayout layout.
     * @param group the data group of the axis lines and labels
     * @param layout an {@link AxisLayout} instance to model this layout after.
     * The axis type and range model of the provided instance will be used.
     * @param bounds the layout bounds within which to place the axis marks
     * @param spacing the minimum spacing between axis labels
     */
    public AxisLabelLayout(String group, AxisLayout layout, Rectangle2D bounds,
            double spacing)
    {
        super(group);
        if ( bounds != null )
            setLayoutBounds(bounds);
        m_layout = layout;
        m_model = layout.getRangeModel();
        m_axis = layout.getAxis();
        m_scale = layout.getScale();
        m_spacing = spacing;
    }
    
    // ------------------------------------------------------------------------
    
    /**
     * Get the formatter used to format labels for numerical values.
     * @return the <code>NumberFormat</code> used to format numerical labels.
     */
    public NumberFormat getNumberFormat() {
        return m_nf;
    }

    /**
     * Set the formatter used to format labels for numerical values.
     * @param nf the <code>NumberFormat</code> used to format numerical labels.
     */
    public void setNumberFormat(NumberFormat nf) {
        m_nf = nf;
    }
    
    /**
     * Get the required minimum spacing between axis labels.
     * @return the axis label spacing
     */
    public double getSpacing() {
        return m_spacing;
    }

    /**
     * Set the required minimum spacing between axis labels.
     * @param spacing the axis label spacing to use
     */
    public void setSpacing(double spacing) {
        m_spacing = spacing;
    }
    
    /**
     * Returns the scale type used for the axis. This setting only applies
     * for numerical data types (i.e., when axis values are from a
     * <code>NumberValuedRange</code>).
     * @return the scale type. One of
     * {@link prefuse.Constants#LINEAR_SCALE}, 
     * {@link prefuse.Constants#SQRT_SCALE}, or
     * {@link Constants#LOG_SCALE}.
     */
    public int getScale() {
        return m_scale;
    }
    
    /**
     * Sets the scale type used for the axis. This setting only applies
     * for numerical data types (i.e., when axis values are from a
     * <code>NumberValuedRange</code>).
     * @param scale the scale type. One of
     * {@link prefuse.Constants#LINEAR_SCALE}, 
     * {@link prefuse.Constants#SQRT_SCALE}, or
     * {@link Constants#LOG_SCALE}.
     */
    public void setScale(int scale) {
        if ( scale < 0 || scale >= Constants.SCALE_COUNT ) {
            throw new IllegalArgumentException(
                "Unrecognized scale type: "+scale);
        }
        m_scale = scale;
    }
    
    /**
     * Indicates if the axis values should be presented in ascending order
     * along the axis.
     * @return true if data values increase as pixel coordinates increase,
     * false if data values decrease as pixel coordinates increase.
     */
    public boolean isAscending() {
        return m_asc;
    }
    
    /**
     * Sets if the axis values should be presented in ascending order
     * along the axis.
     * @param asc true if data values should increase as pixel coordinates
     * increase, false if data values should decrease as pixel coordinates
     * increase.
     */
    public void setAscending(boolean asc) {
        m_asc = asc;
    }
    
    /**
     * Sets the range model used to layout this axis.
     * @param model the range model
     */
    public void setRangeModel(ValuedRangeModel model) {
        m_model = model;
    }
    
    // ------------------------------------------------------------------------
    
    /**
     * @see prefuse.action.GroupAction#run(double)
     */
    public void run(double frac) {
        if ( m_model == null && m_layout != null )
            m_model = m_layout.getRangeModel();
        
        if ( m_model == null ) {
            Logger.getLogger(this.getClass().getName())
                .warning("Axis labels missing a range model.");
            return;
        }
        
        VisualTable labels = getTable();
        
        // check the axis label group to see if we can get a
        // more precise reading of the previous scale
        Double dfrac = (Double)labels.getClientProperty(FRAC);
        double fr = dfrac==null ? 1.0 : dfrac.doubleValue();
        m_prevlo = m_prevlo + fr*(m_lo-m_prevlo);
        m_prevhi = m_prevhi + fr*(m_hi-m_prevhi);
        
        // now compute the layout
        if ( m_model instanceof ObjectRangeModel )
        {   // ordinal layout
            // get the current high and low values
            m_lo = m_model.getValue();
            m_hi = m_lo + m_model.getExtent();
            
            // compute the layout
            ordinalLayout(labels);
        }
        else
        {   // numerical layout   
            // get the current high and low values
            m_lo = ((Number)m_model.getLowValue()).doubleValue();
            m_hi = ((Number)m_model.getHighValue()).doubleValue();
            
            // compute the layout
            switch ( m_scale ) {
            case Constants.LOG_SCALE:
                logLayout(labels);
                break;
            case Constants.SQRT_SCALE:
                sqrtLayout(labels);
                break;
            case Constants.LINEAR_SCALE:
            default:
                linearLayout(labels);
            }
        }
        
        // get rid of any labels that are no longer being used
        garbageCollect(labels);
    }
    
    // ------------------------------------------------------------------------
    // Quantitative Axis Layout

    /**
     * Calculates a quantitative, linearly scaled layout.
     */
    protected void linearLayout(VisualTable labels) {
        Rectangle2D b = getLayoutBounds();
        double breadth = getBreadth(b);
        
        double span = m_hi-m_lo;
        double pspan = m_prevhi-m_prevlo;
        double vlo = 0;
        if ( m_lo >= 0 ) {
            vlo = Math.pow(10, Math.floor(MathLib.log10(m_lo)));
        } else {
            vlo = -Math.pow(10, 1+Math.floor(MathLib.log10(-m_lo)));
        }
        //if ( vlo == 10 || vlo == 1 || vlo == 0.1 ) vlo = 0;
        
        // mark previously visible labels
        Iterator iter = labels.tuples();
        while ( iter.hasNext() ) {
            VisualItem item = (VisualItem)iter.next();
            reset(item);
            double v = item.getDouble(VALUE);
            double x = span==0 ? 0 : ((v-m_lo)/span)*breadth;
            set(item, x, b);
        }

        Index index = labels.index(VALUE);
        double step = getLinearStep(span, span==0 ? 0 : breadth/span);
        if ( step == 0 ) step = 1;
        int r;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?