All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sim.util.media.chart.TimeSeriesAttributes Maven / Gradle / Ivy

Go to download

MASON is a fast discrete-event multiagent simulation library core in Java, designed to be the foundation for large custom-purpose Java simulations, and also to provide more than enough functionality for many lightweight simulation needs. MASON contains both a model library and an optional suite of visualization tools in 2D and 3D.

The newest version!
/*
  Copyright 2006 by Sean Luke and George Mason University
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/

package sim.util.media.chart;

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.event.*;
import java.util.*;
import sim.util.gui.*;
import sim.util.*;

// From JFreeChart
import org.jfree.data.xy.*;
import org.jfree.chart.*;
import org.jfree.chart.event.*;
import org.jfree.chart.plot.*;
import org.jfree.data.general.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.data.general.*;

/** A SeriesAttributes used for user control pf time series created with TimeSeriesCharGenerator.
    This is done largely through the
    manipulation of XYSeries objects and features of the XYPlot class. */
        
public class TimeSeriesAttributes extends SeriesAttributes
    {
    /** A dash */
    static final float DASH = 6;
    /** A dot */
    static final float DOT = 1;
    /** A short space */            
    static final float SPACE = 3;
    /** A long space */
    static final float SKIP = DASH;
    
    public static final int PATTERN_SOLID = 0;
    public static final int PATTERN_LONG_DASH = 1;
    public static final int PATTERN_STRETCH_DASH = 2;
    public static final int PATTERN_DASH = 3;
    public static final int PATTERN_DASH_DASH_DOT = 4;
    public static final int PATTERN_DASH_DOT = 5;
    public static final int PATTERN_DASH_DOT_DOT = 6;
    public static final int PATTERN_DOT = 7;
    public static final int PATTERN_STRETCH_DOT = 8;

    /** Nine dash combinations that the user might find helpful. */
    static final float[][] dashPatterns = 
        { 
        { DASH, 0.0f }, // --------
            { DASH * 2, SKIP }, // -- -- --
            { DASH, SKIP } , // -  -  -  
            { DASH, SPACE } , // - - - -
            { DASH, SPACE, DASH, SPACE, DOT, SPACE },  // - - . - - . 
            { DASH, SPACE, DOT, SPACE, }, // - . - .
            { DASH, SPACE, DOT, SPACE, DOT, SPACE },  // - . . - . . 
            { DOT, SPACE }, // . . . .
            { DOT, SKIP }   // .  .  .  .  
        };
    
    /** How much we should stretch the dashPatterns listed above.  1.0 is normal. */
    float stretch;
    NumberTextField stretchField;
    /** Line thickness. */
    float thickness;
    NumberTextField thicknessField;
    /** Line dash pattern (one of the dashPatterns above). */
    int dashPattern;
    JComboBox dashPatternList;
    /** Line color. */
    Color strokeColor;
    ColorWell strokeColorWell;
                
    public void setThickness(double value) { thicknessField.setValue(thicknessField.newValue(value));  }
    public double getThickness() { return (double)(thicknessField.getValue()); }

    public void setStretch(double value) { stretchField.setValue(stretchField.newValue(value));  }
    public double getStretch() { return (double)(stretchField.getValue()); }

    public void setDashPattern(int value) 
        { 
        if (value >= 0 && value < dashPatterns.length) 
            { 
            dashPatternList.setSelectedIndex(value);
            dashPattern = value;
            }
        }
    public int getDashPattern() { return dashPatternList.getSelectedIndex(); }

    public void setStrokeColor(Color value) { strokeColorWell.setColor(strokeColor = value);}
    public Color getStrokeColor() { return strokeColor; }

    /** The time series in question.  */
    XYSeries series;
    public XYSeries getSeries() { return series; }
    /** Clears the existing internal XYSeries, then adds all the series elements in the provided XYSeries to the
        internal XYSeries.  Does not notify the chart to update.
    */
    public void setSeries(XYSeries series) 
        {
        this.series.clear();
        int count = series.getItemCount();
        for(int i = 0; i < count; i++)
            this.series.add(series.getDataItem(i), true);
        }  
        
    public void setSeriesName(String val) { series.setKey(new ChartGenerator.UniqueString(val)); }  // bypasses super.setSeriesName
    public String getSeriesName() { return "" + series.getKey(); }  // bypasses super.getSeriesName
    
    public void clear() { series.clear(); }
    
    /** Builds a TimeSeriesAttributes with the given generator, series, and index for the series. */
    public TimeSeriesAttributes(ChartGenerator generator, XYSeries series, int index, SeriesChangeListener stoppable)
        { 
        super(generator, "" + series.getKey(), index, stoppable);
        this.series = series;
        }

    public void rebuildGraphicsDefinitions()
        {
        float[] newDashPattern = new float[dashPatterns[dashPattern].length];
        for(int x=0;x 0)
                newDashPattern[x] = dashPatterns[dashPattern][x] * stretch * thickness;  // include thickness so we dont' get overlaps -- will this confuse users?
                
        XYItemRenderer renderer = (XYItemRenderer)(((XYPlot)getPlot()).getRenderer());
            
        // we do two different BasicStroke options here because recent versions of Java (for example, 1.6.0_35_b10-428-11M3811 on Retina Displays)
        // break when defining solid strokes as { X, 0.0 } even though that's perfecty cromulent.  So instead we hack it so that the "solid" stroke
        // is done using a different constructor.
            
        renderer.setSeriesStroke(getSeriesIndex(),
                ((dashPattern == 0) ? // solid
                new BasicStroke(thickness, BasicStroke.CAP_ROUND,
                    BasicStroke.JOIN_ROUND, 0) :
                new BasicStroke(thickness, BasicStroke.CAP_ROUND, 
                    BasicStroke.JOIN_ROUND,0,newDashPattern,0)));

        renderer.setSeriesPaint(getSeriesIndex(),strokeColor);
        repaint();
        }
        
    public void buildAttributes()
        {
        // The following three variables aren't defined until AFTER construction if
        // you just define them above.  So we define them below here instead.
                                                
        dashPattern = 0; // dashPatterns[0];
        stretch = 1.0f;
        thickness = 2.0f;

        // strokeColor = Color.black;  // rebuildGraphicsDefinitions will get called by our caller afterwards
        XYItemRenderer renderer = (((XYPlot)getPlot()).getRenderer());

        // NOTE:
        // Paint paint = renderer.getSeriesPaint(getSeriesIndex());        
        // In JFreeChart 1.0.6 getSeriesPaint returns null!!!
        // You need lookupSeriesPaint(), but that's not backward compatible.
        // The only thing consistent in all versions is getItemPaint 
        // (which looks like a gross miss-use, but gets the job done)
                
        Paint paint = renderer.getItemPaint(getSeriesIndex(), -1);
        
        strokeColor = (Color)paint;
        
        strokeColorWell = new ColorWell(strokeColor)
            {
            public Color changeColor(Color c) 
                {
                strokeColor = c;
                rebuildGraphicsDefinitions();
                return c;
                }
            };
        addLabelled("Color",strokeColorWell);
                        
        thicknessField = new NumberTextField(2.0,true)
            {
            public double newValue(double newValue) 
                {
                if (newValue < 0.0) 
                    newValue = currentValue;
                thickness = (float)newValue;
                rebuildGraphicsDefinitions();
                return newValue;
                }
            };
        addLabelled("Width",thicknessField);
        
        dashPatternList = new JComboBox();
        dashPatternList.setEditable(false);
        dashPatternList.setModel(new DefaultComboBoxModel(new java.util.Vector(Arrays.asList(
                        new String[] { "Solid", "__  __  __", "_  _  _  _", "_ _ _ _ _", "_ _ . _ _ .", 
                                       "_ . _ . _ .", "_ . . _ . .", ". . . . . . .", ".  .  .  .  ." }))));
        dashPatternList.setSelectedIndex(0);
        dashPatternList.addActionListener(new ActionListener()
            {
            public void actionPerformed ( ActionEvent e )
                {
                dashPattern = dashPatternList.getSelectedIndex(); // dashPatterns[dashPatternList.getSelectedIndex()];
                rebuildGraphicsDefinitions();
                }
            });
        addLabelled("Dash",dashPatternList);
        stretchField = new NumberTextField(1.0,true)
            {
            public double newValue(double newValue) 
                {
                if (newValue < 0.0) 
                    newValue = currentValue;
                stretch = (float)newValue;
                rebuildGraphicsDefinitions();
                return newValue;
                }
            };
        addLabelled("Stretch",stretchField);
        }


    public boolean possiblyCull()
        {
        DataCuller dataCuller = ((TimeSeriesChartGenerator)generator).getDataCuller();
        if(dataCuller!=null && dataCuller.tooManyPoints(series.getItemCount()))
            {
            deleteItems(dataCuller.cull(getXValues(), true));
            return true;
            }
        else
            return false;
        }
                
    void deleteItems(IntBag items)
        {
        Bag tmpBag = new Bag();
        
        if(items.numObjs==0)
            return;

        int currentTabooIndex = 0;
        int currentTaboo = items.objs[0];
        Iterator iter = series.getItems().iterator();
        int index=0;
        while(iter.hasNext())
            {
            Object o = iter.next();
            if(index==currentTaboo)
                {
                //skip the copy, let's move on to next taboo index
                if(currentTabooIndex




© 2015 - 2025 Weber Informatics LLC | Privacy Policy