/* | |
* Copyright 2012 AndroidPlot.com | |
* | |
* 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 com.androidplot.demos; | |
import android.app.Activity; | |
import android.graphics.Color; | |
import android.graphics.DashPathEffect; | |
import android.graphics.Paint; | |
import android.os.Bundle; | |
import android.widget.CheckBox; | |
import android.widget.CompoundButton; | |
import com.androidplot.util.PixelUtils; | |
import com.androidplot.xy.XYSeries; | |
import com.androidplot.ui.*; | |
import com.androidplot.xy.*; | |
import java.text.DecimalFormat; | |
import java.text.FieldPosition; | |
import java.text.NumberFormat; | |
import java.text.ParsePosition; | |
import java.util.Arrays; | |
/** | |
* Demonstration of the usage of Marker and RectRegion. | |
*/ | |
public class XYRegionExampleActivity extends Activity { | |
private static final float HOME_RUN_DIST = 325; | |
private static final int LINE_THICKNESS_DP = 2; | |
private static final int POINT_SIZE_DP = 6; | |
private XYPlot plot; | |
private final Number[] timHits = {105, 252, 220, 350, 12, 250, 353}; | |
private final Number[] nickHits = {110, 191, 61, 371, 289, 101, 10}; | |
private final Number[] joeHits = {25, 375, 364, 128, 178, 289, 346}; | |
private final Number[] jamesHits = {250, 285, 295, 211, 311, 365, 241}; | |
private LineAndPointFormatter timFormatter; | |
private LineAndPointFormatter nickFormatter; | |
private LineAndPointFormatter joeFormatter; | |
private LineAndPointFormatter jamesFormatter; | |
private XYSeries timSeries; | |
private XYSeries nickSeries; | |
private XYSeries joeSeries; | |
private XYSeries jamesSeries; | |
private RectRegion shortRegion; | |
private RectRegion warmupRegion; | |
private RectRegion homeRunRegion; | |
//private XYRegionFormatter rf1; | |
private XYRegionFormatter shortRegionFormatter; | |
private XYRegionFormatter warmupRegionFormatter; | |
private XYRegionFormatter homeRunRegionFormatter; | |
//private XYRegionFormatter rf5; | |
private CheckBox timCB; | |
private CheckBox nickCB; | |
private CheckBox joeCB; | |
private CheckBox jamesCB; | |
private CheckBox r2CheckBox; | |
private CheckBox r3CheckBox; | |
private CheckBox r4CheckBox; | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.xyregion_example); | |
plot = (XYPlot) findViewById(R.id.xyRegionExamplePlot); | |
timCB = (CheckBox) findViewById(R.id.s1CheckBox); | |
timCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |
@Override | |
public void onCheckedChanged(CompoundButton compoundButton, boolean b) { | |
onS1CheckBoxClicked(); | |
} | |
}); | |
nickCB = (CheckBox) findViewById(R.id.s2CheckBox); | |
nickCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |
@Override | |
public void onCheckedChanged(CompoundButton compoundButton, boolean b) { | |
onS2CheckBoxClicked(); | |
} | |
}); | |
joeCB = (CheckBox) findViewById(R.id.s3CheckBox); | |
joeCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |
@Override | |
public void onCheckedChanged(CompoundButton compoundButton, boolean b) { | |
onS3CheckBoxClicked(); | |
} | |
}); | |
jamesCB = (CheckBox) findViewById(R.id.s4CheckBox); | |
jamesCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |
@Override | |
public void onCheckedChanged(CompoundButton compoundButton, boolean b) { | |
onS4CheckBoxClicked(); | |
} | |
}); | |
r2CheckBox = (CheckBox) findViewById(R.id.r2CheckBox); | |
r2CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |
@Override | |
public void onCheckedChanged(CompoundButton compoundButton, boolean b) { | |
onCheckBoxClicked(r2CheckBox, timFormatter, shortRegionFormatter, shortRegion); | |
} | |
}); | |
r3CheckBox = (CheckBox) findViewById(R.id.r3CheckBox); | |
r3CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |
@Override | |
public void onCheckedChanged(CompoundButton compoundButton, boolean b) { | |
onCheckBoxClicked(r3CheckBox, nickFormatter, warmupRegionFormatter, warmupRegion); | |
} | |
}); | |
r4CheckBox = (CheckBox) findViewById(R.id.r4CheckBox); | |
r4CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |
@Override | |
public void onCheckedChanged(CompoundButton compoundButton, boolean b) { | |
onCheckBoxClicked(r4CheckBox, nickFormatter, homeRunRegionFormatter, homeRunRegion); | |
} | |
}); | |
seriesSetup(); | |
markerSetup(); | |
axisLabelSetup(); | |
regionSetup(); | |
makePlotPretty(); | |
} | |
private void onS1CheckBoxClicked() { | |
if(timCB.isChecked()) { | |
plot.addSeries(timSeries, timFormatter); | |
r2CheckBox.setEnabled(true); | |
} else { | |
plot.removeSeries(timSeries); | |
r2CheckBox.setEnabled(false); | |
} | |
plot.redraw(); | |
} | |
private void onS2CheckBoxClicked() { | |
if(nickCB.isChecked()) { | |
plot.addSeries(nickSeries, nickFormatter); | |
r3CheckBox.setEnabled(true); | |
r4CheckBox.setEnabled(true); | |
} else { | |
plot.removeSeries(nickSeries); | |
r3CheckBox.setEnabled(false); | |
r4CheckBox.setEnabled(false); | |
} | |
plot.redraw(); | |
} | |
private void onS3CheckBoxClicked() { | |
if(joeCB.isChecked()) { | |
plot.addSeries(joeSeries, joeFormatter); | |
} else { | |
plot.removeSeries(joeSeries); | |
} | |
plot.redraw(); | |
} | |
private void onS4CheckBoxClicked() { | |
if(jamesCB.isChecked()) { | |
plot.addSeries(jamesSeries, jamesFormatter); | |
} else { | |
plot.removeSeries(jamesSeries); | |
} | |
plot.redraw(); | |
} | |
/** | |
* Processes a check box event | |
* @param cb The checkbox event origin | |
* @param lpf LineAndPointFormatter with which rr and rf are to be added/removed | |
* @param rf The XYRegionFormatter with which rr should be rendered | |
* @param rr The RectRegion to add/remove | |
*/ | |
private void onCheckBoxClicked(CheckBox cb, LineAndPointFormatter lpf, | |
XYRegionFormatter rf, RectRegion rr) { | |
if(cb.isChecked()) { | |
lpf.removeRegion(rr); | |
} else { | |
lpf.addRegion(rr, rf); | |
} | |
} | |
/** | |
* Cleans up the plot's general layout and color scheme | |
*/ | |
private void makePlotPretty() { | |
// use a 2x5 grid with room for 10 items: | |
plot.getLegendWidget().setTableModel(new DynamicTableModel(4, 2)); | |
// add a semi-transparent black background to the legend | |
// so it's easier to see overlaid on top of our plot: | |
Paint bgPaint = new Paint(); | |
bgPaint.setColor(Color.BLACK); | |
bgPaint.setStyle(Paint.Style.FILL); | |
bgPaint.setAlpha(40); | |
plot.getLegendWidget().setBackgroundPaint(bgPaint); | |
// adjust the padding of the legend widget to look a little nicer: | |
plot.getLegendWidget().setPadding(5, 5, 5, 5); | |
plot.setRangeValueFormat(new NumberFormat() { | |
@Override | |
public StringBuffer format(double value, StringBuffer buffer, FieldPosition field) { | |
return new StringBuffer(value + "'"); | |
} | |
@Override | |
public StringBuffer format(long value, StringBuffer buffer, FieldPosition field) { | |
throw new UnsupportedOperationException("Not yet implemented."); | |
} | |
@Override | |
public Number parse(String string, ParsePosition position) { | |
throw new UnsupportedOperationException("Not yet implemented."); | |
} | |
}); | |
plot.setDomainValueFormat(new DecimalFormat("#")); | |
plot.getLegendWidget().setWidth(PixelUtils.dpToPix(100), SizeLayoutType.FILL); | |
// adjust the legend size so there is enough room | |
// to draw the new legend grid: | |
//plot.getLegendWidget().getHeightMetric().setLayoutType(SizeLayoutType.ABSOLUTE); | |
//plot.getLegendWidget().getWidthMetric().setLayoutType(SizeLayoutType.ABSOLUTE); | |
//plot.getLegendWidget().setSize( | |
// new SizeMetrics(70, SizeLayoutType.ABSOLUTE, 80, SizeLayoutType.ABSOLUTE)); | |
// reposition the grid so that it rests above the bottom-left | |
// edge of the graph widget: | |
plot.getLegendWidget().position( | |
125, | |
XLayoutStyle.ABSOLUTE_FROM_LEFT, | |
65, | |
YLayoutStyle.ABSOLUTE_FROM_TOP, | |
AnchorPosition.LEFT_TOP); | |
plot.getGraphWidget().setRangeLabelHorizontalOffset(-1); | |
// add enough space to ensure range value labels arent cut off on the left/right: | |
plot.getGraphWidget().setRangeLabelWidth(25); | |
// add enough space to make sure domain value labels arent cut off on the bottom: | |
plot.getGraphWidget().setDomainLabelWidth(15); | |
plot.getGraphWidget().setDomainLabelVerticalOffset(-6); | |
plot.setRangeBoundaries(0, BoundaryMode.FIXED, 500, BoundaryMode.FIXED); | |
} | |
/** | |
* Create 4 XYSeries from the values defined above add add them to the plot. | |
* Also add some arbitrary regions. | |
*/ | |
private void seriesSetup() { | |
// TIM | |
timFormatter = new LineAndPointFormatter( | |
Color.rgb(100, 25, 20), | |
Color.rgb(100, 25, 20), | |
null, null); | |
timFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP)); | |
timFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP)); | |
timSeries = new SimpleXYSeries(Arrays.asList(timHits), | |
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Tim"); | |
plot.addSeries(timSeries, timFormatter); | |
// SERIES #2: | |
nickFormatter = new LineAndPointFormatter( | |
Color.rgb(100, 25, 200), | |
Color.rgb(100, 25, 200), | |
null, null); | |
nickFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP)); | |
nickFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP)); | |
nickSeries = new SimpleXYSeries(Arrays.asList(nickHits), | |
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Nick"); | |
plot.addSeries(nickSeries, nickFormatter); | |
// SERIES #3: | |
joeFormatter = new LineAndPointFormatter( | |
Color.rgb(200, 25, 200), | |
Color.rgb(200, 25, 200), | |
null, null); | |
joeFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP)); | |
joeFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP)); | |
joeSeries = new SimpleXYSeries(Arrays.asList(joeHits), | |
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Joe"); | |
plot.addSeries(joeSeries, joeFormatter); | |
// SERIES #4: | |
jamesFormatter = new LineAndPointFormatter( | |
Color.rgb(220, 25, 20), | |
Color.rgb(220, 25, 20), | |
null, null); | |
jamesFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP)); | |
jamesFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP)); | |
jamesSeries = new SimpleXYSeries(Arrays.asList(jamesHits), | |
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY,"James"); | |
plot.addSeries(jamesSeries, jamesFormatter); | |
plot.setRangeStep(XYStepMode.INCREMENT_BY_VAL, 100); | |
//plot.setTicksPerRangeLabel(1); | |
plot.setDomainStep(XYStepMode.INCREMENT_BY_VAL, 1); | |
} | |
/** | |
* Add some color coded regions to our axis labels. | |
*/ | |
private void axisLabelSetup() { | |
// DOMAIN | |
plot.getGraphWidget().addDomainAxisValueLabelRegion( | |
Double.NEGATIVE_INFINITY, 2, new AxisValueLabelFormatter(Color.GRAY)); | |
plot.getGraphWidget().addDomainAxisValueLabelRegion( | |
2, Double.POSITIVE_INFINITY, new AxisValueLabelFormatter(Color.WHITE)); | |
// RANGE | |
plot.getGraphWidget().addRangeAxisValueLabelRegion( | |
Double.NEGATIVE_INFINITY, HOME_RUN_DIST, new AxisValueLabelFormatter(Color.RED)); | |
plot.getGraphWidget().addRangeAxisValueLabelRegion( | |
HOME_RUN_DIST, Double.POSITIVE_INFINITY, new AxisValueLabelFormatter(Color.GREEN)); | |
} | |
/** | |
* Add some markers to our plot. | |
*/ | |
private void markerSetup() { | |
YValueMarker fenwayLfMarker = new YValueMarker( | |
380, // y-val to mark | |
"Fenway Park LF Wall", // marker label | |
new XPositionMetric( // object instance to set text positioning on the marker | |
PixelUtils.dpToPix(5), // 5dp offset | |
XLayoutStyle.ABSOLUTE_FROM_RIGHT), // offset origin | |
Color.BLUE, // line paint color | |
Color.BLUE); // text paint color | |
YValueMarker attRfMarker = new YValueMarker( | |
309, // y-val to mark | |
"ATT Park RF Wall", // marker label | |
new XPositionMetric( // object instance to set text positioning on the marker | |
PixelUtils.dpToPix(5), // 5dp offset | |
XLayoutStyle.ABSOLUTE_FROM_RIGHT), // offset origin | |
Color.CYAN, // line paint color | |
Color.CYAN); // text paint color | |
fenwayLfMarker.getTextPaint().setTextSize(PixelUtils.dpToPix(14)); | |
attRfMarker.getTextPaint().setTextSize(PixelUtils.dpToPix(14)); | |
DashPathEffect dpe = new DashPathEffect( | |
new float[]{PixelUtils.dpToPix(2), PixelUtils.dpToPix(2)}, 0); | |
fenwayLfMarker.getLinePaint().setPathEffect(dpe); | |
attRfMarker.getLinePaint().setPathEffect(dpe); | |
plot.addMarker(fenwayLfMarker); | |
plot.addMarker(attRfMarker); | |
} | |
/** | |
* Add some fill regions to our series data | |
*/ | |
private void regionSetup() { | |
// and another region: | |
shortRegionFormatter = new XYRegionFormatter(Color.RED); | |
shortRegionFormatter.getPaint().setAlpha(75); | |
shortRegion = new RectRegion(2, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, HOME_RUN_DIST, "Short"); | |
timFormatter.addRegion(shortRegion, shortRegionFormatter); | |
nickFormatter.addRegion(shortRegion, shortRegionFormatter); | |
joeFormatter.addRegion(shortRegion, shortRegionFormatter); | |
jamesFormatter.addRegion(shortRegion, shortRegionFormatter); | |
// the next three regions are horizontal regions with minY/maxY | |
// set to negative and positive infinity respectively. | |
warmupRegionFormatter = new XYRegionFormatter(Color.WHITE); | |
warmupRegionFormatter.getPaint().setAlpha(75); | |
warmupRegion = new RectRegion(0, 2, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, "Warmup"); | |
timFormatter.addRegion(warmupRegion, warmupRegionFormatter); | |
nickFormatter.addRegion(warmupRegion, warmupRegionFormatter); | |
joeFormatter.addRegion(warmupRegion, warmupRegionFormatter); | |
jamesFormatter.addRegion(warmupRegion, warmupRegionFormatter); | |
homeRunRegionFormatter = new XYRegionFormatter(Color.GREEN); | |
homeRunRegionFormatter.getPaint().setAlpha(75); | |
homeRunRegion = new RectRegion(2, Double.POSITIVE_INFINITY, HOME_RUN_DIST, Double.POSITIVE_INFINITY, "H. Run"); | |
timFormatter.addRegion(homeRunRegion, homeRunRegionFormatter); | |
nickFormatter.addRegion(homeRunRegion, homeRunRegionFormatter); | |
joeFormatter.addRegion(homeRunRegion, homeRunRegionFormatter); | |
jamesFormatter.addRegion(homeRunRegion, homeRunRegionFormatter); | |
nickFormatter.setFillDirection(FillDirection.RANGE_ORIGIN); | |
} | |
} |