Android Open Source - SDCardTrac Graph View






From Project

Back to project page SDCardTrac.

License

The source code is released under:

GNU General Public License

If you think the Android project SDCardTrac listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * This file is part of GraphView.// w w  w  .ja  v  a 2s . c om
 *
 * GraphView is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * GraphView is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GraphView.  If not, see <http://www.gnu.org/licenses/lgpl.html>.
 *
 * Copyright Jonas Gehring
 */

package com.jjoe64.graphview;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;

import com.jjoe64.graphview.GraphViewSeries.GraphViewSeriesStyle;
import com.jjoe64.graphview.GraphViewStyle.GridStyle;
import com.jjoe64.graphview.compatible.ScaleGestureDetector;

/**
 * GraphView is a Android View for creating zoomable and scrollable graphs.
 * This is the abstract base class for all graphs. Extend this class and implement {@link #drawSeries(android.graphics.Canvas, GraphViewDataInterface[], float, float, float, double, double, double, double, float, com.jjoe64.graphview.GraphViewSeries.GraphViewSeriesStyle)} to display a custom graph.
 * Use {@link com.jjoe64.graphview.LineGraphView} for creating a line chart.
 *
 * @author jjoe64 - jonas gehring - http://www.jjoe64.com
 *
 * Copyright (C) 2011 Jonas Gehring
 * Licensed under the GNU Lesser General Public License (LGPL)
 * http://www.gnu.org/licenses/lgpl.html
 */
abstract public class GraphView extends LinearLayout {
  static final private class GraphViewConfig {
    static final float BORDER = 20;
  }

  private class GraphViewContentView extends View {
    private float lastTouchEventX;
    private float graphwidth;
    private boolean scrollingStarted;
        static final float RESIST_MOVE_THRESHOLD = 2.0f; // difference in X to not detect as move
        private float origDown;

    /**
     * @param context
     */
    public GraphViewContentView(Context context) {
      super(context);
      setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    }

    /**
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {

      paint.setAntiAlias(true);

      // normal
      paint.setStrokeWidth(0);

      float border = GraphViewConfig.BORDER;
      float horstart = 0;
      float height = getHeight();
      float width = getWidth() - 1;
      double maxY = getMaxY();
      double minY = getMinY();
      double maxX = getMaxX(false);
      double minX = getMinX(false);
      double diffX = maxX - minX;

       // measure bottom text
      if (labelTextHeight == null || horLabelTextWidth == null) {
        paint.setTextSize(getGraphViewStyle().getTextSize());
        double testX = ((getMaxX(true)-getMinX(true))*0.783)+getMinX(true);
        String testLabel = formatLabel(testX, true, 0, 0);
        paint.getTextBounds(testLabel, 0, testLabel.length(), textBounds);
        labelTextHeight = (textBounds.height());
        horLabelTextWidth = (textBounds.width());
      }
            border += labelTextHeight;

      float graphheight = height - (2 * border);
      graphwidth = width;

      if (horlabels == null) {
        horlabels = generateHorlabels(graphwidth);
      }
      if (verlabels == null) {
        verlabels = generateVerlabels(graphheight);
      }

      // vertical lines
      if(graphViewStyle.getGridStyle() != GridStyle.HORIZONTAL) {
        paint.setTextAlign(Align.LEFT);
        int vers = verlabels.length - 1;
        for (int i = 0; i < verlabels.length; i++) {
          paint.setColor(graphViewStyle.getGridColor());
          float y = ((graphheight / vers) * i) + border;
          canvas.drawLine(horstart, y, width, y, paint);
        }
      }

      drawHorizontalLabels(canvas, border, horstart, height, horlabels, graphwidth);

            paint.setColor(graphViewStyle.getHorizontalLabelsColor());
      paint.setTextAlign(Align.CENTER);
      canvas.drawText(title, (graphwidth / 2) + horstart, border - 4, paint);

      if (maxY == minY) {
        // if min/max is the same, fake it so that we can render a line
        if(maxY == 0) {
          // if both are zero, change the values to prevent division by zero
          maxY = 1.0d;
          minY = 0.0d;
        } else {
          maxY = maxY*1.05d;
          minY = minY*0.95d;
        }
      }

      double diffY = maxY - minY;
      paint.setStrokeCap(Paint.Cap.ROUND);

      for (int i=0; i<graphSeries.size(); i++) {
        drawSeries(canvas, _values(i), graphwidth, graphheight, border, minX, minY, diffX, diffY, horstart, graphSeries.get(i).style);
      }

      if (showLegend) drawLegend(canvas, height, width);
    }

    private void onMoveGesture(float f) {
      // view port update
      if (viewportSize != 0) {
        viewportStart -= f*viewportSize/graphwidth;

        // minimal and maximal view limit
        double minX = getMinX(true);
        double maxX = getMaxX(true);
        if (viewportStart < minX) {
          viewportStart = minX;
        } else if (viewportStart+viewportSize > maxX) {
          viewportStart = maxX - viewportSize;
        }

        // labels have to be regenerated
        if (!staticHorizontalLabels) horlabels = null;
        if (!staticVerticalLabels) verlabels = null;
        viewVerLabels.invalidate();
      }
      // Invalidate selection
      for (int i=0; i<graphSeries.size(); i++) {
          graphSeries.get(i).style.highlightPoints = false;
      }
      invalidate();
    }

    /**
     * @param event
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //if (!isScrollable() || isDisableTouch()) {
        if (isDisableTouch()) {
        return super.onTouchEvent(event);
      }

      boolean handled = false;
      // first scale
      if (scalable && scaleDetector != null) {
        scaleDetector.onTouchEvent(event);
        handled = scaleDetector.isInProgress();
      }
      if (!handled) {
                boolean hadMoved = false;

        // if not scaled, scroll
        if ((event.getAction() & MotionEvent.ACTION_DOWN) == MotionEvent.ACTION_DOWN &&
            (event.getAction() & MotionEvent.ACTION_MOVE) == 0) {
          scrollingStarted = true;
          handled = true;

                    if (!((event.getAction() & MotionEvent.ACTION_UP) == MotionEvent.ACTION_UP)) {
                        origDown = event.getX();
                        handleSelect(event, false, false, 0);
                    }
        }
        if ((event.getAction() & MotionEvent.ACTION_UP) == MotionEvent.ACTION_UP) {
                    if ((lastTouchEventX != 0) && !resistMove(origDown, event.getX())) hadMoved = true;
                    else hadMoved = false;

                    scrollingStarted = false;
          lastTouchEventX = 0;
          handled = true;

                    // Sample select callback
                    if (!hadMoved) {
                        handleSelect(event, true, false, 0);
                    }
        }
        if ((event.getAction() & MotionEvent.ACTION_MOVE) == MotionEvent.ACTION_MOVE) {
            if (isScrollable() && scrollingStarted) {
            if (lastTouchEventX != 0) {
              onMoveGesture(event.getX() - lastTouchEventX);
            }
            lastTouchEventX = event.getX();
            handled = true;
          }
        }

                //Log.d("GraphView", "on touch event scale not handled " + lastTouchEventX
                //        + " event " + event.toString() + " moved " + hadMoved + " ox " + origDown);

                if (handled)
          invalidate();
      } else {
        // currently scaling
        scrollingStarted = false;
        lastTouchEventX = 0;
      }
      return handled;
    }

        // Resist a move if movement is small
        private boolean resistMove(float initX, float finalX) {
            if (Math.abs(initX - finalX) > RESIST_MOVE_THRESHOLD) {
                return false;
            } else {
                return true;
            }
        }
  }

  /**
   * one data set for a graph series
   */
  static public class GraphViewData implements GraphViewDataInterface {
    public final double valueX;
    public final double valueY;
    public GraphViewData(double valueX, double valueY) {
      super();
      this.valueX = valueX;
      this.valueY = valueY;
    }
    @Override
    public double getX() {
      return valueX;
    }
    @Override
    public double getY() {
      return valueY;
    }
  }

  public enum LegendAlign {
    TOP, MIDDLE, BOTTOM
  }

  private class VerLabelsView extends View {
    /**
     * @param context
     */
    public VerLabelsView(Context context) {
      super(context);
      setLayoutParams(new LayoutParams(
          getGraphViewStyle().getVerticalLabelsWidth()==0?100:getGraphViewStyle().getVerticalLabelsWidth()
              , LayoutParams.FILL_PARENT));
    }

    /**
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
      // normal
      paint.setStrokeWidth(0);

       // measure bottom text
      if (labelTextHeight == null || verLabelTextWidth == null) {
        paint.setTextSize(getGraphViewStyle().getTextSize());
        double testY = ((getMaxY()-getMinY())*0.783)+getMinY();
        String testLabel = formatLabel(testY, false, 0, 0);
        paint.getTextBounds(testLabel, 0, testLabel.length(), textBounds);
        labelTextHeight = (textBounds.height());
        verLabelTextWidth = (textBounds.width());
      }
      if (getGraphViewStyle().getVerticalLabelsWidth()==0 && getLayoutParams().width != verLabelTextWidth+GraphViewConfig.BORDER) {
        setLayoutParams(new LayoutParams(
            (int) (verLabelTextWidth+GraphViewConfig.BORDER), LayoutParams.FILL_PARENT));
      } else if (getGraphViewStyle().getVerticalLabelsWidth()!=0 && getGraphViewStyle().getVerticalLabelsWidth() != getLayoutParams().width) {
        setLayoutParams(new LayoutParams(
            getGraphViewStyle().getVerticalLabelsWidth(), LayoutParams.FILL_PARENT));
      }

      float border = GraphViewConfig.BORDER;
      border += labelTextHeight;
      float height = getHeight();
      float graphheight = height - (2 * border);

      if (verlabels == null) {
        verlabels = generateVerlabels(graphheight);
      }

      // vertical labels
      paint.setTextAlign(getGraphViewStyle().getVerticalLabelsAlign());
      int labelsWidth = getWidth();
      int labelsOffset = 0;
      if (getGraphViewStyle().getVerticalLabelsAlign() == Align.RIGHT) {
        labelsOffset = labelsWidth;
      } else if (getGraphViewStyle().getVerticalLabelsAlign() == Align.CENTER) {
        labelsOffset = labelsWidth / 2;
      }
      int vers = verlabels.length - 1;
      for (int i = 0; i < verlabels.length; i++) {
        float y = ((graphheight / vers) * i) + border;
        paint.setColor(graphViewStyle.getVerticalLabelsColor());
        canvas.drawText(verlabels[i], labelsOffset, y, paint);
      }

      // reset
      paint.setTextAlign(Align.LEFT);
    }
  }

    // Arguments are the event that occured and whether that finishes the select
    private boolean handleSelect(MotionEvent inEvent, boolean finished, boolean force,
                                 int forceSelect) {
        GraphViewDataInterface[] data;

        boolean retVal = false;
        data = graphSeries.get(0).values;

        if (finished) {
            int selectIndex = 1;
            double selectSample = 0;
            int startPoint = 0;
            boolean viewBefore = false;

            // Calculate nearest sample point
            if (force && forceSelect < data.length)
                selectSample = data[forceSelect].getX();
            else
                selectSample = GraphView.this.transformPointToSample
                        (inEvent.getX(), GraphViewConfig.BORDER, graphViewContentView.getWidth());

            for (GraphViewDataInterface i : data) {
                if (i.getX() >= selectSample) {
                    break;
                }
                if (i.getX() < viewportStart) {
                    startPoint = selectIndex;
                    viewBefore = true;
                }
                selectIndex++;
            }
            if (viewBefore)
                startPoint++;
            else
                startPoint = 0;

            if (selectIndex >= data.length)
                selectIndex = data.length - 1;

            boolean redrawIt = false;
            // Check if point is in view
            if (viewportSize != 0) {
                if (data[selectIndex].getX() > (viewportStart + viewportSize)) {
                    viewportStart = data[selectIndex].getX() - (viewportSize / 2);
                    redrawIt = true;
                } else if (data[selectIndex].getX() < viewportStart) {
                    if (data[selectIndex].getX() > (viewportSize / 2))
                    viewportStart = data[selectIndex].getX() - (viewportSize / 2);
                    else
                    viewportStart = data[selectIndex].getX();
                    redrawIt = true;
                }

                if (redrawIt)
                    redrawAll();
            } else
                startPoint = 0;

            // Call overriden method
            if (selectHandler != null && !redrawIt)
                selectHandler.onGraphSelect(selectIndex, startPoint);
            retVal = !redrawIt;
        }

        return retVal;
    }

    // Helper to move to selected index
    public void gotoSample(int seriesInd, int sampleInd) {
        GraphViewDataInterface[] data;

        data = graphSeries.get(seriesInd).values;
        if (sampleInd < data.length) {
            handleSelect(null, true, true, sampleInd);
        }
    }

    abstract public interface GraphSelectHandler {
        // Function to call overridable user callback for select events
        abstract public void onGraphSelect(int selectIndex, int startPoint);
    }

  protected final Paint paint;
  private String[] horlabels;
  private String[] verlabels;
  private String title;
  private boolean scrollable;
  private boolean disableTouch;
  private double viewportStart;
  private double viewportSize;
  private final View viewVerLabels;
  private ScaleGestureDetector scaleDetector;
  private boolean scalable;
  private final NumberFormat[] numberformatter = new NumberFormat[2];
  private final List<GraphViewSeries> graphSeries;
  private boolean showLegend = false;
  private LegendAlign legendAlign = LegendAlign.MIDDLE;
  private boolean manualYAxis;
  private boolean manualMaxY;
      private boolean manualMinY;
  private double manualMaxYValue;
  private double manualMinYValue;
  protected GraphViewStyle graphViewStyle;
  private final GraphViewContentView graphViewContentView;
  private CustomLabelFormatter customLabelFormatter;
  private Integer labelTextHeight;
  private Integer horLabelTextWidth;
  private Integer verLabelTextWidth;
  private final Rect textBounds = new Rect();
  private boolean staticHorizontalLabels;
  private boolean staticVerticalLabels;
    private boolean showHorizontalLabels = true;
    private boolean showVerticalLabels = true;
    private GraphSelectHandler selectHandler;

  public GraphView(Context context, AttributeSet attrs) {
    this(context, attrs.getAttributeValue(null, "title"));

    int width = attrs.getAttributeIntValue("android", "layout_width", LayoutParams.MATCH_PARENT);
    int height = attrs.getAttributeIntValue("android", "layout_height", LayoutParams.MATCH_PARENT);
    setLayoutParams(new LayoutParams(width, height));
  }

  /**
   * @param context
   * @param title [optional]
   */
  public GraphView(Context context, String title) {
    super(context);
    setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

    if (title == null)
      this.title = "";
    else
      this.title = title;

    graphViewStyle = new GraphViewStyle();
    graphViewStyle.useTextColorFromTheme(context);

    paint = new Paint();
    graphSeries = new ArrayList<GraphViewSeries>();

    viewVerLabels = new VerLabelsView(context);
    addView(viewVerLabels);
    graphViewContentView = new GraphViewContentView(context);
    addView(graphViewContentView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, 1));
  }

  private GraphViewDataInterface[] _values(int idxSeries) {
    GraphViewDataInterface[] values = graphSeries.get(idxSeries).values;
    synchronized (values) {
      if (viewportStart == 0 && viewportSize == 0) {
        // all data
        return values;
      } else {
        // viewport
        List<GraphViewDataInterface> listData = new ArrayList<GraphViewDataInterface>();
        for (int i=0; i<values.length; i++) {
          if (values[i].getX() >= viewportStart) {
            if (values[i].getX() > viewportStart+viewportSize) {
              listData.add(values[i]); // one more for nice scrolling
              break;
            } else {
              listData.add(values[i]);
            }
          } else {
            if (listData.isEmpty()) {
              listData.add(values[i]);
            }
            listData.set(0, values[i]); // one before, for nice scrolling
          }
        }
        return listData.toArray(new GraphViewDataInterface[listData.size()]);
      }
    }
  }

  /**
   * add a series of data to the graph
   * @param series
   */
  public void addSeries(GraphViewSeries series) {
    series.addGraphView(this);
    graphSeries.add(series);
    redrawAll();
  }

  protected void drawHorizontalLabels(Canvas canvas, float border,
      float horstart, float height, String[] horlabels, float graphwidth) {
    // horizontal labels + lines
    int hors = horlabels.length - 1;
    for (int i = 0; i < horlabels.length; i++) {
      paint.setColor(graphViewStyle.getGridColor());
      float x = ((graphwidth / hors) * i) + horstart;
      if(graphViewStyle.getGridStyle() != GridStyle.VERTICAL) {
        canvas.drawLine(x, height - border, x, border, paint);
      }
            if(showHorizontalLabels) {
                paint.setTextAlign(Align.CENTER);
                if (i==horlabels.length-1)
                    paint.setTextAlign(Align.RIGHT);
                if (i==0)
                    paint.setTextAlign(Align.LEFT);
                paint.setColor(graphViewStyle.getHorizontalLabelsColor());
                canvas.drawText(horlabels[i], x, height - 4, paint);
            }
    }
  }

  protected void drawLegend(Canvas canvas, float height, float width) {
    float textSize = paint.getTextSize();
    int spacing = getGraphViewStyle().getLegendSpacing();
    int border = getGraphViewStyle().getLegendBorder();
    int legendWidth = getGraphViewStyle().getLegendWidth();

    int shapeSize = (int) (textSize*0.8d);
    Log.d("GraphView", "draw legend size: "+paint.getTextSize());

    // rect
    paint.setARGB(180, 100, 100, 100);
    float legendHeight = (shapeSize+spacing)*graphSeries.size() +2*border -spacing;
    float lLeft = width-legendWidth - border*2;
    float lTop;
    switch (legendAlign) {
    case TOP:
      lTop = 0;
      break;
    case MIDDLE:
      lTop = height/2 - legendHeight/2;
      break;
    default:
      lTop = height - GraphViewConfig.BORDER - legendHeight - getGraphViewStyle().getLegendMarginBottom();
    }
    float lRight = lLeft+legendWidth;
    float lBottom = lTop+legendHeight;
    canvas.drawRoundRect(new RectF(lLeft, lTop, lRight, lBottom), 8, 8, paint);

    for (int i=0; i<graphSeries.size(); i++) {
      paint.setColor(graphSeries.get(i).style.color);
      canvas.drawRect(new RectF(lLeft+border, lTop+border+(i*(shapeSize+spacing)), lLeft+border+shapeSize, lTop+border+(i*(shapeSize+spacing))+shapeSize), paint);
      if (graphSeries.get(i).description != null) {
        paint.setColor(Color.WHITE);
        paint.setTextAlign(Align.LEFT);
        canvas.drawText(graphSeries.get(i).description, lLeft+border+shapeSize+spacing, lTop+border+shapeSize+(i*(shapeSize+spacing)), paint);
      }
    }
  }

  abstract protected void drawSeries(Canvas canvas, GraphViewDataInterface[] values, float graphwidth, float graphheight, float border, double minX, double minY, double diffX, double diffY, float horstart, GraphViewSeriesStyle style);

    /** 
     * Highlights a sample in the graph. Graph should be redrawn after this call
     * 
     * @param series and sample index to be highlighted, enable flag
     */
    public void highlightSample(int seriesIndex, boolean enable, int sampleIndex) {
  if (graphSeries.get(seriesIndex) != null) {
      graphSeries.get(seriesIndex).style.highlightPoints = enable;
      graphSeries.get(seriesIndex).style.highlightSample = sampleIndex;
      // Redraw the graph
      redrawAll();
  }
    }

  /**
   * formats the label
   * use #setCustomLabelFormatter or static labels if you want custom labels
   *
   * @param value x and y values
   * @param isValueX if false, value y wants to be formatted
   * @deprecated use {@link #setCustomLabelFormatter(CustomLabelFormatter)}
   * @return value to display
   */

  @Deprecated
  protected String formatLabel(double value, boolean isValueX, int index, int lastIndex) {
    if (customLabelFormatter != null) {
        String label = customLabelFormatter.formatLabel(value, isValueX, index, lastIndex);
      if (label != null) {
        return label;
      }
    }
    int i = isValueX ? 1 : 0;
    if (numberformatter[i] == null) {
      numberformatter[i] = NumberFormat.getNumberInstance();
      double highestvalue = isValueX ? getMaxX(false) : getMaxY();
      double lowestvalue = isValueX ? getMinX(false) : getMinY();
      if (highestvalue - lowestvalue < 0.1) {
        numberformatter[i].setMaximumFractionDigits(6);
      } else if (highestvalue - lowestvalue < 1) {
        numberformatter[i].setMaximumFractionDigits(4);
      } else if (highestvalue - lowestvalue < 20) {
        numberformatter[i].setMaximumFractionDigits(3);
      } else if (highestvalue - lowestvalue < 100) {
        numberformatter[i].setMaximumFractionDigits(1);
      } else {
        numberformatter[i].setMaximumFractionDigits(0);
      }
    }
    return numberformatter[i].format(value);
  }

  private String[] generateHorlabels(float graphwidth) {
    int numLabels = getGraphViewStyle().getNumHorizontalLabels()-1;
    if (numLabels < 0) {
      if (graphwidth <= 0) graphwidth = 1f;
      numLabels = (int) (graphwidth/(horLabelTextWidth*2));
    }

    String[] labels = new String[numLabels+1];
    double min = getMinX(false);
    double max = getMaxX(false);
    for (int i=0; i<=numLabels; i++) {
        labels[i] = formatLabel(min + ((max-min)*i/numLabels), true, i, numLabels);
    }
    return labels;
  }

  synchronized private String[] generateVerlabels(float graphheight) {
    int numLabels = getGraphViewStyle().getNumVerticalLabels()-1;
    if (numLabels < 0) {
      if (graphheight <= 0) graphheight = 1f;
      numLabels = (int) (graphheight/(labelTextHeight*3));
      if (numLabels == 0) {
        Log.w("GraphView", "Height of Graph is smaller than the label text height, so no vertical labels were shown!");
      }
    }
    String[] labels = new String[numLabels+1];
    double min = getMinY();
    double max = getMaxY();
    if (max == min) {
      // if min/max is the same, fake it so that we can render a line
      if(max == 0) {
        // if both are zero, change the values to prevent division by zero
        max = 1.0d;
        min = 0.0d;
      } else {
        max = max*1.05d;
        min = min*0.95d;
      }
    }

    for (int i=0; i<=numLabels; i++) {
        labels[numLabels-i] = formatLabel(min + ((max-min)*i/numLabels), false, i, numLabels);
    }
    return labels;
  }

  /**
   * @return the custom label formatter, if there is one. otherwise null
   */
  public CustomLabelFormatter getCustomLabelFormatter() {
    return customLabelFormatter;
  }

  /**
   * @return the graphview style. it will never be null.
   */
  public GraphViewStyle getGraphViewStyle() {
    return graphViewStyle;
  }

  /**
   * get the position of the legend
   * @return
   */
  public LegendAlign getLegendAlign() {
    return legendAlign;
  }

  /**
   * @return legend width
   * @deprecated use {@link GraphViewStyle#getLegendWidth()}
   */
  @Deprecated
  public float getLegendWidth() {
    return getGraphViewStyle().getLegendWidth();
  }

  /**
   * returns the maximal X value of the current viewport (if viewport is set)
   * otherwise maximal X value of all data.
   * @param ignoreViewport
   *
   * warning: only override this, if you really know want you're doing!
   */
  protected double getMaxX(boolean ignoreViewport) {
    // if viewport is set, use this
    if (!ignoreViewport && viewportSize != 0) {
      return viewportStart+viewportSize;
    } else {
      // otherwise use the max x value
      // values must be sorted by x, so the last value has the largest X value
      double highest = 0;
      if (graphSeries.size() > 0) {
        GraphViewDataInterface[] values = graphSeries.get(0).values;
        if (values.length == 0) {
          highest = 0;
        } else {
          highest = values[values.length-1].getX();
        }
        for (int i=1; i<graphSeries.size(); i++) {
          values = graphSeries.get(i).values;
          if (values.length > 0) {
            highest = Math.max(highest, values[values.length-1].getX());
          }
        }
      }
      return highest;
    }
  }

  /**
   * returns the maximal Y value of all data.
   *
   * warning: only override this, if you really know want you're doing!
   */
  protected double getMaxY() {
    double largest;
    if (manualYAxis || manualMaxY) {
      largest = manualMaxYValue;
    } else {
      largest = Integer.MIN_VALUE;
      for (int i=0; i<graphSeries.size(); i++) {
        GraphViewDataInterface[] values = _values(i);
        for (int ii=0; ii<values.length; ii++)
          if (values[ii].getY() > largest)
            largest = values[ii].getY();
      }
    }
    return largest;
  }

  /**
   * returns the minimal X value of the current viewport (if viewport is set)
   * otherwise minimal X value of all data.
   * @param ignoreViewport
   *
   * warning: only override this, if you really know want you're doing!
   */
  protected double getMinX(boolean ignoreViewport) {
    // if viewport is set, use this
    if (!ignoreViewport && viewportSize != 0) {
      return viewportStart;
    } else {
      // otherwise use the min x value
      // values must be sorted by x, so the first value has the smallest X value
      double lowest = 0;
      if (graphSeries.size() > 0) {
        GraphViewDataInterface[] values = graphSeries.get(0).values;
        if (values.length == 0) {
          lowest = 0;
        } else {
          lowest = values[0].getX();
        }
        for (int i=1; i<graphSeries.size(); i++) {
          values = graphSeries.get(i).values;
          if (values.length > 0) {
            lowest = Math.min(lowest, values[0].getX());
          }
        }
      }
      return lowest;
    }
  }

  /**
   * returns the minimal Y value of all data.
   *
   * warning: only override this, if you really know want you're doing!
   */
  protected double getMinY() {
    double smallest;
    if (manualYAxis || manualMinY) {
      smallest = manualMinYValue;
    } else {
      smallest = Integer.MAX_VALUE;
      for (int i=0; i<graphSeries.size(); i++) {
        GraphViewDataInterface[] values = _values(i);
        for (int ii=0; ii<values.length; ii++)
          if (values[ii].getY() < smallest)
            smallest = values[ii].getY();
      }
    }
    return smallest;
  }
  
  /**
   * returns the size of the Viewport
   * 
   */
  public double getViewportSize(){
    return viewportSize;
  }
    public double getViewportStart() {
  return viewportStart;
    }

  public boolean isDisableTouch() {
    return disableTouch;
  }

  public boolean isScrollable() {
    return scrollable;
  }

  public boolean isShowLegend() {
    return showLegend;
  }

  /**
   * forces graphview to invalide all views and caches.
   * Normally there is no need to call this manually.
   */
  public void redrawAll() {
    if (!staticVerticalLabels) verlabels = null;
    if (!staticHorizontalLabels) horlabels = null;
    numberformatter[0] = null;
    numberformatter[1] = null;
    labelTextHeight = null;
    horLabelTextWidth = null;
    verLabelTextWidth = null;

    invalidate();
    viewVerLabels.invalidate();
    graphViewContentView.invalidate();
  }

  /**
   * removes all series
   */
  public void removeAllSeries() {
    for (GraphViewSeries s : graphSeries) {
      s.removeGraphView(this);
    }
    while (!graphSeries.isEmpty()) {
      graphSeries.remove(0);
    }
    redrawAll();
  }

  /**
   * removes a series
   * @param series series to remove
   */
  public void removeSeries(GraphViewSeries series) {
    series.removeGraphView(this);
    graphSeries.remove(series);
    redrawAll();
  }

  /**
   * removes series
   * @param index
   */
  public void removeSeries(int index) {
    if (index < 0 || index >= graphSeries.size()) {
      throw new IndexOutOfBoundsException("No series at index " + index);
    }

    removeSeries(graphSeries.get(index));
  }

  /**
   * scrolls to the last x-value
   * @throws IllegalStateException if scrollable == false
   */
  public void scrollToEnd() {
    if (!scrollable) throw new IllegalStateException("This GraphView is not scrollable.");
    double max = getMaxX(true);
    viewportStart = max-viewportSize;

    // don't clear labels width/height cache
    // so that the display is not flickering
    if (!staticVerticalLabels) verlabels = null;
    if (!staticHorizontalLabels) horlabels = null;

    invalidate();
    viewVerLabels.invalidate();
    graphViewContentView.invalidate();
  }

  /**
   * set a custom label formatter
   * @param customLabelFormatter
   */
  public void setCustomLabelFormatter(CustomLabelFormatter customLabelFormatter) {
    this.customLabelFormatter = customLabelFormatter;
  }

  /**
   * The user can disable any touch gestures, this is useful if you are using a real time graph, but don't want the user to interact
   * @param disableTouch
   */
  public void setDisableTouch(boolean disableTouch) {
    this.disableTouch = disableTouch;
  }

  /**
   * set custom graphview style
   * @param style
   */
  public void setGraphViewStyle(GraphViewStyle style) {
    graphViewStyle = style;
    labelTextHeight = null;
  }

  /**
   * set's static horizontal labels (from left to right)
   * @param horlabels if null, labels were generated automatically
   */
  public void setHorizontalLabels(String[] horlabels) {
    staticHorizontalLabels = horlabels != null;
    this.horlabels = horlabels;
  }

  /**
   * legend position
   * @param legendAlign
   */
  public void setLegendAlign(LegendAlign legendAlign) {
    this.legendAlign = legendAlign;
  }

  /**
   * legend width
   * @param legendWidth
   * @deprecated use {@link GraphViewStyle#setLegendWidth(int)}
   */
  @Deprecated
  public void setLegendWidth(float legendWidth) {
    getGraphViewStyle().setLegendWidth((int)legendWidth);
  }

  /**
   * you have to set the bounds {@link #setManualYAxisBounds(double, double)}. That automatically enables manualYAxis-flag.
   * if you want to disable the menual y axis, call this method with false.
   * @param manualYAxis
   */
  public void setManualYAxis(boolean manualYAxis) {
    this.manualYAxis = manualYAxis;
  }
  
  /**
   * if you want to disable the menual y axis maximum bound, call this method with false.
   */
  public void setManualMaxY(boolean manualMaxY) {
          this.manualMaxY = manualMaxY;
      }
      
      /**
   * if you want to disable the menual y axis minimum bound, call this method with false.
   */
      public void setManualMinY(boolean manualMinY) {
          this.manualMinY = manualMinY;
   }

  /**
   * set manual Y axis limit
   * @param max
   * @param min
   */
  public void setManualYAxisBounds(double max, double min) {
    manualMaxYValue = max;
    manualMinYValue = min;
    manualYAxis = true;
  }
  
  /*
   * set manual Y axis max limit
   * @param max
   */
  public void setManualYMaxBound(double max) {
          manualMaxYValue = max;
          manualMaxY = true;
      }

  /*
   * set manual Y axis min limit
   * @param min
   */
      public void setManualYMinBound(double min) {
          manualMinYValue = min;
          manualMinY = true;
      }

  /**
   * this forces scrollable = true
   * @param scalable
   */
  synchronized public void setScalable(boolean scalable) {
    this.scalable = scalable;
    if (scalable == true && scaleDetector == null) {
      scrollable = true; // automatically forces this
      scaleDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.SimpleOnScaleGestureListener() {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
          double center = viewportStart + viewportSize / 2;
          viewportSize /= detector.getScaleFactor();
          viewportStart = center - viewportSize / 2;

          // viewportStart must not be < minX
          double minX = getMinX(true);
          if (viewportStart < minX) {
            viewportStart = minX;
          }

          // viewportStart + viewportSize must not be > maxX
          double maxX = getMaxX(true);
          if (viewportSize == 0) {
            viewportSize = maxX;
          }
          double overlap = viewportStart + viewportSize - maxX;
          if (overlap > 0) {
            // scroll left
            if (viewportStart-overlap > minX) {
              viewportStart -= overlap;
            } else {
              // maximal scale
              viewportStart = minX;
              viewportSize = maxX - viewportStart;
            }
          }
          redrawAll();
          return true;
        }
      });
    }
  }

  /**
   * the user can scroll (horizontal) the graph. This is only useful if you use a viewport {@link #setViewPort(double, double)} which doesn't displays all data.
   * @param scrollable
   */
  public void setScrollable(boolean scrollable) {
    this.scrollable = scrollable;
  }

  public void setShowLegend(boolean showLegend) {
    this.showLegend = showLegend;
  }

  /**
   * sets the title of graphview
   * @param title
   */
  public void setTitle(String title) {
    this.title = title;
  }

  /**
   * set's static vertical labels (from top to bottom)
   * @param verlabels if null, labels were generated automatically
   */
  public void setVerticalLabels(String[] verlabels) {
    staticVerticalLabels = verlabels != null;
    this.verlabels = verlabels;
  }

  /**
   * set's the viewport for the graph.
   * @see #setManualYAxisBounds(double, double) to limit the y-viewport
   * @param start x-value
   * @param size
   */
  public void setViewPort(double start, double size) {
    if (size<0) {
      throw new IllegalArgumentException("Viewport size must be greater than 0!");
    }
    viewportStart = start;
    viewportSize = size;
  }

    /**
     * Sets whether horizontal labels are drawn or not.
     *
     * @param showHorizontalLabels
     */
    public void setShowHorizontalLabels(boolean showHorizontalLabels) {
        this.showHorizontalLabels = showHorizontalLabels;
        redrawAll();
    }

    /**
     * Gets are horizontal labels drawn.
     *
     * @return {@code True} if horizontal labels are drawn
     */
    public boolean getShowHorizontalLabels() {
        return showHorizontalLabels;
    }

    /**
     * Sets whether vertical labels are drawn or not.
     *
     * @param showVerticalLabels
     */
    public void setShowVerticalLabels(boolean showVerticalLabels) {
        this.showVerticalLabels = showVerticalLabels;
        if(this.showVerticalLabels) {
            addView(viewVerLabels, 0);
        } else {
            removeView(viewVerLabels);
        }
    }

    /**
     * Gets are vertical labels are drawn.
     *
     * @return {@code True} if vertical labels are drawn
     */
    public boolean getShowVerticalLabels() {
        return showVerticalLabels;
    }

    /*
     * For OnSelect callback
     */
    /**
     * Set's the select handler class for 1st series in graph
     * @param handle instance
     */
    public void setSelectHandler(GraphSelectHandler handle) {
        selectHandler = handle;
    }

    abstract double transformPointToSample(double point, float border, int wid);
}




Java Source Code List

com.jjoe64.graphview.BarGraphView.java
com.jjoe64.graphview.CustomLabelFormatter.java
com.jjoe64.graphview.GraphViewDataInterface.java
com.jjoe64.graphview.GraphViewSeries.java
com.jjoe64.graphview.GraphViewStyle.java
com.jjoe64.graphview.GraphView.java
com.jjoe64.graphview.LineGraphView.java
com.jjoe64.graphview.ValueDependentColor.java
com.jjoe64.graphview.compatible.RealScaleGestureDetector.java
com.jjoe64.graphview.compatible.ScaleGestureDetector.java
com.nma.util.sdcardtrac.AlarmHelper.java
com.nma.util.sdcardtrac.BitcoinIntegration.java
com.nma.util.sdcardtrac.ChangeLogFragment.java
com.nma.util.sdcardtrac.DatabaseLoader.java
com.nma.util.sdcardtrac.DatabaseManager.java
com.nma.util.sdcardtrac.DeleteDataPreference.java
com.nma.util.sdcardtrac.DeltaCompute.java
com.nma.util.sdcardtrac.FileObserverService.java
com.nma.util.sdcardtrac.GraphActivity.java
com.nma.util.sdcardtrac.GraphFragment.java
com.nma.util.sdcardtrac.GraphTabListener.java
com.nma.util.sdcardtrac.HelpFragment.java
com.nma.util.sdcardtrac.MyExpandableListAdapter.java
com.nma.util.sdcardtrac.SQLiteHelper.java
com.nma.util.sdcardtrac.SearchableActivity.java
com.nma.util.sdcardtrac.SettingsActivity.java
com.nma.util.sdcardtrac.StorageHelper.java
com.nma.util.sdcardtrac.UsageFileObserver.java