Home | History | Annotate | Download | only in demos
      1 /*
      2  * Copyright 2012 AndroidPlot.com
      3  *
      4  *    Licensed under the Apache License, Version 2.0 (the "License");
      5  *    you may not use this file except in compliance with the License.
      6  *    You may obtain a copy of the License at
      7  *
      8  *        http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  *    Unless required by applicable law or agreed to in writing, software
     11  *    distributed under the License is distributed on an "AS IS" BASIS,
     12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  *    See the License for the specific language governing permissions and
     14  *    limitations under the License.
     15  */
     16 
     17 package com.androidplot.demos;
     18 
     19 import android.app.Activity;
     20 import android.graphics.Color;
     21 import android.graphics.DashPathEffect;
     22 import android.graphics.Paint;
     23 import android.os.Bundle;
     24 import android.widget.CheckBox;
     25 import android.widget.CompoundButton;
     26 import com.androidplot.util.PixelUtils;
     27 import com.androidplot.xy.XYSeries;
     28 import com.androidplot.ui.*;
     29 import com.androidplot.xy.*;
     30 
     31 import java.text.DecimalFormat;
     32 import java.text.FieldPosition;
     33 import java.text.NumberFormat;
     34 import java.text.ParsePosition;
     35 import java.util.Arrays;
     36 
     37 /**
     38  * Demonstration of the usage of Marker and RectRegion.
     39  */
     40 public class XYRegionExampleActivity extends Activity {
     41 
     42     private static final float HOME_RUN_DIST = 325;
     43     private static final int LINE_THICKNESS_DP = 2;
     44     private static final int POINT_SIZE_DP = 6;
     45     private XYPlot plot;
     46     private final Number[] timHits = {105, 252, 220, 350, 12, 250, 353};
     47     private final Number[] nickHits = {110, 191, 61, 371, 289, 101, 10};
     48     private final Number[] joeHits = {25, 375, 364, 128, 178, 289, 346};
     49     private final Number[] jamesHits = {250, 285, 295, 211, 311, 365, 241};
     50     private LineAndPointFormatter timFormatter;
     51     private LineAndPointFormatter nickFormatter;
     52     private LineAndPointFormatter joeFormatter;
     53     private LineAndPointFormatter jamesFormatter;
     54 
     55     private XYSeries timSeries;
     56     private XYSeries nickSeries;
     57     private XYSeries joeSeries;
     58     private XYSeries jamesSeries;
     59 
     60     private RectRegion shortRegion;
     61     private RectRegion warmupRegion;
     62     private RectRegion homeRunRegion;
     63 
     64     //private XYRegionFormatter rf1;
     65     private XYRegionFormatter shortRegionFormatter;
     66     private XYRegionFormatter warmupRegionFormatter;
     67     private XYRegionFormatter homeRunRegionFormatter;
     68     //private XYRegionFormatter rf5;
     69 
     70     private CheckBox timCB;
     71     private CheckBox nickCB;
     72     private CheckBox joeCB;
     73     private CheckBox jamesCB;
     74 
     75     private CheckBox r2CheckBox;
     76     private CheckBox r3CheckBox;
     77     private CheckBox r4CheckBox;
     78 
     79     public void onCreate(Bundle savedInstanceState) {
     80         super.onCreate(savedInstanceState);
     81         setContentView(R.layout.xyregion_example);
     82         plot = (XYPlot) findViewById(R.id.xyRegionExamplePlot);
     83         timCB = (CheckBox) findViewById(R.id.s1CheckBox);
     84         timCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
     85             @Override
     86             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
     87                 onS1CheckBoxClicked();
     88             }
     89         });
     90 
     91         nickCB = (CheckBox) findViewById(R.id.s2CheckBox);
     92         nickCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
     93             @Override
     94             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
     95                 onS2CheckBoxClicked();
     96             }
     97         });
     98 
     99         joeCB = (CheckBox) findViewById(R.id.s3CheckBox);
    100         joeCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    101             @Override
    102             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
    103                 onS3CheckBoxClicked();
    104             }
    105         });
    106 
    107         jamesCB = (CheckBox) findViewById(R.id.s4CheckBox);
    108         jamesCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    109             @Override
    110             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
    111                 onS4CheckBoxClicked();
    112             }
    113         });
    114 
    115 
    116 
    117         r2CheckBox = (CheckBox) findViewById(R.id.r2CheckBox);
    118         r2CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    119             @Override
    120             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
    121                 onCheckBoxClicked(r2CheckBox, timFormatter, shortRegionFormatter, shortRegion);
    122             }
    123         });
    124 
    125         r3CheckBox = (CheckBox) findViewById(R.id.r3CheckBox);
    126         r3CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    127             @Override
    128             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
    129                 onCheckBoxClicked(r3CheckBox, nickFormatter, warmupRegionFormatter, warmupRegion);
    130             }
    131         });
    132 
    133         r4CheckBox = (CheckBox) findViewById(R.id.r4CheckBox);
    134         r4CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    135             @Override
    136             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
    137                 onCheckBoxClicked(r4CheckBox, nickFormatter, homeRunRegionFormatter, homeRunRegion);
    138             }
    139         });
    140 
    141         seriesSetup();
    142         markerSetup();
    143         axisLabelSetup();
    144         regionSetup();
    145         makePlotPretty();
    146     }
    147 
    148     private void onS1CheckBoxClicked() {
    149         if(timCB.isChecked()) {
    150             plot.addSeries(timSeries, timFormatter);
    151             r2CheckBox.setEnabled(true);
    152         } else {
    153             plot.removeSeries(timSeries);
    154             r2CheckBox.setEnabled(false);
    155         }
    156         plot.redraw();
    157     }
    158 
    159     private void onS2CheckBoxClicked() {
    160         if(nickCB.isChecked()) {
    161             plot.addSeries(nickSeries, nickFormatter);
    162             r3CheckBox.setEnabled(true);
    163             r4CheckBox.setEnabled(true);
    164         } else {
    165             plot.removeSeries(nickSeries);
    166             r3CheckBox.setEnabled(false);
    167             r4CheckBox.setEnabled(false);
    168         }
    169         plot.redraw();
    170     }
    171 
    172     private void onS3CheckBoxClicked() {
    173         if(joeCB.isChecked()) {
    174             plot.addSeries(joeSeries, joeFormatter);
    175         } else {
    176             plot.removeSeries(joeSeries);
    177         }
    178         plot.redraw();
    179     }
    180 
    181     private void onS4CheckBoxClicked() {
    182         if(jamesCB.isChecked()) {
    183             plot.addSeries(jamesSeries, jamesFormatter);
    184         } else {
    185             plot.removeSeries(jamesSeries);
    186         }
    187         plot.redraw();
    188     }
    189 
    190     /**
    191      * Processes a check box event
    192      * @param cb The checkbox event origin
    193      * @param lpf LineAndPointFormatter with which rr and rf are to be added/removed
    194      * @param rf The XYRegionFormatter with which rr should be rendered
    195      * @param rr The RectRegion to add/remove
    196      */
    197     private void onCheckBoxClicked(CheckBox cb, LineAndPointFormatter lpf,
    198                                    XYRegionFormatter rf, RectRegion rr) {
    199         if(cb.isChecked()) {
    200             lpf.removeRegion(rr);
    201         } else {
    202             lpf.addRegion(rr, rf);
    203         }
    204     }
    205 
    206     /**
    207      * Cleans up the plot's general layout and color scheme
    208      */
    209     private void makePlotPretty() {
    210         // use a 2x5 grid with room for 10 items:
    211         plot.getLegendWidget().setTableModel(new DynamicTableModel(4, 2));
    212 
    213         // add a semi-transparent black background to the legend
    214         // so it's easier to see overlaid on top of our plot:
    215         Paint bgPaint = new Paint();
    216         bgPaint.setColor(Color.BLACK);
    217         bgPaint.setStyle(Paint.Style.FILL);
    218         bgPaint.setAlpha(40);
    219 
    220         plot.getLegendWidget().setBackgroundPaint(bgPaint);
    221 
    222         // adjust the padding of the legend widget to look a little nicer:
    223         plot.getLegendWidget().setPadding(5, 5, 5, 5);
    224 
    225         plot.setRangeValueFormat(new NumberFormat() {
    226             @Override
    227             public StringBuffer format(double value, StringBuffer buffer, FieldPosition field) {
    228                 return new StringBuffer(value + "'");
    229             }
    230 
    231             @Override
    232             public StringBuffer format(long value, StringBuffer buffer, FieldPosition field) {
    233                 throw new UnsupportedOperationException("Not yet implemented.");
    234             }
    235 
    236             @Override
    237             public Number parse(String string, ParsePosition position) {
    238                 throw new UnsupportedOperationException("Not yet implemented.");
    239             }
    240         });
    241 
    242         plot.setDomainValueFormat(new DecimalFormat("#"));
    243 
    244         plot.getLegendWidget().setWidth(PixelUtils.dpToPix(100), SizeLayoutType.FILL);
    245 
    246 
    247         // adjust the legend size so there is enough room
    248         // to draw the new legend grid:
    249         //plot.getLegendWidget().getHeightMetric().setLayoutType(SizeLayoutType.ABSOLUTE);
    250         //plot.getLegendWidget().getWidthMetric().setLayoutType(SizeLayoutType.ABSOLUTE);
    251         //plot.getLegendWidget().setSize(
    252         //    new SizeMetrics(70, SizeLayoutType.ABSOLUTE, 80, SizeLayoutType.ABSOLUTE));
    253 
    254         // reposition the grid so that it rests above the bottom-left
    255         // edge of the graph widget:
    256 
    257         plot.getLegendWidget().position(
    258                 125,
    259                 XLayoutStyle.ABSOLUTE_FROM_LEFT,
    260                 65,
    261                 YLayoutStyle.ABSOLUTE_FROM_TOP,
    262                 AnchorPosition.LEFT_TOP);
    263 
    264         plot.getGraphWidget().setRangeLabelHorizontalOffset(-1);
    265 
    266         // add enough space to ensure range value labels arent cut off on the left/right:
    267         plot.getGraphWidget().setRangeLabelWidth(25);
    268 
    269         // add enough space to make sure domain value labels arent cut off on the bottom:
    270         plot.getGraphWidget().setDomainLabelWidth(15);
    271 
    272         plot.getGraphWidget().setDomainLabelVerticalOffset(-6);
    273 
    274         plot.setRangeBoundaries(0, BoundaryMode.FIXED, 500, BoundaryMode.FIXED);
    275     }
    276 
    277     /**
    278      * Create 4 XYSeries from the values defined above add add them to the plot.
    279      * Also add some arbitrary regions.
    280      */
    281     private void seriesSetup() {
    282 
    283 
    284         // TIM
    285         timFormatter = new LineAndPointFormatter(
    286                 Color.rgb(100, 25, 20),
    287                 Color.rgb(100, 25, 20),
    288                 null, null);
    289         timFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP));
    290         timFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP));
    291 
    292         timSeries = new SimpleXYSeries(Arrays.asList(timHits),
    293             SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Tim");
    294 
    295         plot.addSeries(timSeries, timFormatter);
    296 
    297         // SERIES #2:
    298         nickFormatter = new LineAndPointFormatter(
    299                 Color.rgb(100, 25, 200),
    300                 Color.rgb(100, 25, 200),
    301                 null, null);
    302         nickFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP));
    303         nickFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP));
    304 
    305 
    306 
    307         nickSeries = new SimpleXYSeries(Arrays.asList(nickHits),
    308             SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Nick");
    309 
    310         plot.addSeries(nickSeries, nickFormatter);
    311 
    312         // SERIES #3:
    313         joeFormatter = new LineAndPointFormatter(
    314                 Color.rgb(200, 25, 200),
    315                 Color.rgb(200, 25, 200),
    316                 null, null);
    317         joeFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP));
    318         joeFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP));
    319 
    320         joeSeries = new SimpleXYSeries(Arrays.asList(joeHits),
    321             SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Joe");
    322 
    323         plot.addSeries(joeSeries, joeFormatter);
    324 
    325         // SERIES #4:
    326         jamesFormatter = new LineAndPointFormatter(
    327                 Color.rgb(220, 25, 20),
    328                 Color.rgb(220, 25, 20),
    329                 null, null);
    330 
    331         jamesFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP));
    332         jamesFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP));
    333 
    334         jamesSeries = new SimpleXYSeries(Arrays.asList(jamesHits),
    335             SimpleXYSeries.ArrayFormat.Y_VALS_ONLY,"James");
    336         plot.addSeries(jamesSeries, jamesFormatter);
    337 
    338         plot.setRangeStep(XYStepMode.INCREMENT_BY_VAL, 100);
    339         //plot.setTicksPerRangeLabel(1);
    340         plot.setDomainStep(XYStepMode.INCREMENT_BY_VAL, 1);
    341     }
    342 
    343     /**
    344      * Add some color coded regions to our axis labels.
    345      */
    346     private void axisLabelSetup() {
    347         // DOMAIN
    348         plot.getGraphWidget().addDomainAxisValueLabelRegion(
    349                 Double.NEGATIVE_INFINITY, 2, new AxisValueLabelFormatter(Color.GRAY));
    350         plot.getGraphWidget().addDomainAxisValueLabelRegion(
    351                 2, Double.POSITIVE_INFINITY, new AxisValueLabelFormatter(Color.WHITE));
    352         // RANGE
    353         plot.getGraphWidget().addRangeAxisValueLabelRegion(
    354                 Double.NEGATIVE_INFINITY, HOME_RUN_DIST, new AxisValueLabelFormatter(Color.RED));
    355         plot.getGraphWidget().addRangeAxisValueLabelRegion(
    356                 HOME_RUN_DIST, Double.POSITIVE_INFINITY, new AxisValueLabelFormatter(Color.GREEN));
    357     }
    358 
    359     /**
    360      * Add some markers to our plot.
    361      */
    362     private void markerSetup() {
    363 
    364         YValueMarker fenwayLfMarker = new YValueMarker(
    365                 380,                                        // y-val to mark
    366                 "Fenway Park LF Wall",                      // marker label
    367                 new XPositionMetric(                        // object instance to set text positioning on the marker
    368                         PixelUtils.dpToPix(5),              // 5dp offset
    369                         XLayoutStyle.ABSOLUTE_FROM_RIGHT),  // offset origin
    370                 Color.BLUE,                                 // line paint color
    371                 Color.BLUE);                                // text paint color
    372 
    373         YValueMarker attRfMarker = new YValueMarker(
    374                         309,                                        // y-val to mark
    375                         "ATT Park RF Wall",                         // marker label
    376                         new XPositionMetric(                        // object instance to set text positioning on the marker
    377                                 PixelUtils.dpToPix(5),              // 5dp offset
    378                                 XLayoutStyle.ABSOLUTE_FROM_RIGHT),  // offset origin
    379                         Color.CYAN,                                 // line paint color
    380                         Color.CYAN);                                // text paint color
    381 
    382 
    383         fenwayLfMarker.getTextPaint().setTextSize(PixelUtils.dpToPix(14));
    384         attRfMarker.getTextPaint().setTextSize(PixelUtils.dpToPix(14));
    385 
    386         DashPathEffect dpe = new DashPathEffect(
    387                         new float[]{PixelUtils.dpToPix(2), PixelUtils.dpToPix(2)}, 0);
    388 
    389         fenwayLfMarker.getLinePaint().setPathEffect(dpe);
    390         attRfMarker.getLinePaint().setPathEffect(dpe);
    391 
    392         plot.addMarker(fenwayLfMarker);
    393         plot.addMarker(attRfMarker);
    394     }
    395 
    396     /**
    397      * Add some fill regions to our series data
    398      */
    399     private void regionSetup() {
    400 
    401 
    402         // and another region:
    403         shortRegionFormatter = new XYRegionFormatter(Color.RED);
    404         shortRegionFormatter.getPaint().setAlpha(75);
    405         shortRegion = new RectRegion(2, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, HOME_RUN_DIST, "Short");
    406         timFormatter.addRegion(shortRegion, shortRegionFormatter);
    407         nickFormatter.addRegion(shortRegion, shortRegionFormatter);
    408         joeFormatter.addRegion(shortRegion, shortRegionFormatter);
    409         jamesFormatter.addRegion(shortRegion, shortRegionFormatter);
    410 
    411         // the next three regions are horizontal regions with minY/maxY
    412         // set to negative and positive infinity respectively.
    413         warmupRegionFormatter = new XYRegionFormatter(Color.WHITE);
    414         warmupRegionFormatter.getPaint().setAlpha(75);
    415 
    416         warmupRegion = new RectRegion(0, 2, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, "Warmup");
    417         timFormatter.addRegion(warmupRegion, warmupRegionFormatter);
    418         nickFormatter.addRegion(warmupRegion, warmupRegionFormatter);
    419         joeFormatter.addRegion(warmupRegion, warmupRegionFormatter);
    420         jamesFormatter.addRegion(warmupRegion, warmupRegionFormatter);
    421 
    422         homeRunRegionFormatter = new XYRegionFormatter(Color.GREEN);
    423         homeRunRegionFormatter.getPaint().setAlpha(75);
    424 
    425         homeRunRegion = new RectRegion(2, Double.POSITIVE_INFINITY, HOME_RUN_DIST, Double.POSITIVE_INFINITY, "H. Run");
    426         timFormatter.addRegion(homeRunRegion, homeRunRegionFormatter);
    427         nickFormatter.addRegion(homeRunRegion, homeRunRegionFormatter);
    428         joeFormatter.addRegion(homeRunRegion, homeRunRegionFormatter);
    429         jamesFormatter.addRegion(homeRunRegion, homeRunRegionFormatter);
    430 
    431         nickFormatter.setFillDirection(FillDirection.RANGE_ORIGIN);
    432     }
    433 }