Android Open Source - Dual-Battery-Widget Abstract Chart






From Project

Back to project page Dual-Battery-Widget.

License

The source code is released under:

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions f...

If you think the Android project Dual-Battery-Widget 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

/**
 * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
 *  /*  w ww  .j  a v  a  2  s .c om*/
 * 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 org.achartengine.chart;

import java.io.Serializable;
import java.util.List;

import org.achartengine.model.Point;
import org.achartengine.model.SeriesSelection;
import org.achartengine.renderer.DefaultRenderer;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer.Orientation;
import org.achartengine.util.MathHelper;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;

/**
 * An abstract class to be implemented by the chart rendering classes.
 */
public abstract class AbstractChart implements Serializable {
  /**
   * The graphical representation of the chart.
   * 
   * @param canvas the canvas to paint to
   * @param x the top left x value of the view to draw to
   * @param y the top left y value of the view to draw to
   * @param width the width of the view to draw to
   * @param height the height of the view to draw to
   * @param paint the paint
   */
  public abstract void draw(Canvas canvas, int x, int y, int width, int height, Paint paint);

  /**
   * Draws the chart background.
   * 
   * @param renderer the chart renderer
   * @param canvas the canvas to paint to
   * @param x the top left x value of the view to draw to
   * @param y the top left y value of the view to draw to
   * @param width the width of the view to draw to
   * @param height the height of the view to draw to
   * @param paint the paint used for drawing
   * @param newColor if a new color is to be used
   * @param color the color to be used
   */
  protected void drawBackground(DefaultRenderer renderer, Canvas canvas, int x, int y, int width,
      int height, Paint paint, boolean newColor, int color) {
    if (renderer.isApplyBackgroundColor() || newColor) {
      if (newColor) {
        paint.setColor(color);
      } else {
        paint.setColor(renderer.getBackgroundColor());
      }
      paint.setStyle(Style.FILL);
      canvas.drawRect(x, y, x + width, y + height, paint);
    }
  }

  /**
   * Draws the chart legend.
   * 
   * @param canvas the canvas to paint to
   * @param renderer the series renderer
   * @param titles the titles to go to the legend
   * @param left the left X value of the area to draw to
   * @param right the right X value of the area to draw to
   * @param y the y value of the area to draw to
   * @param width the width of the area to draw to
   * @param height the height of the area to draw to
   * @param legendSize the legend size
   * @param paint the paint to be used for drawing
   * @param calculate if only calculating the legend size
   * 
   * @return the legend height
   */
  protected int drawLegend(Canvas canvas, DefaultRenderer renderer, String[] titles, int left,
      int right, int y, int width, int height, int legendSize, Paint paint, boolean calculate) {
    float size = 32;
    if (renderer.isShowLegend()) {
      float currentX = left;
      float currentY = y + height - legendSize + size;
      paint.setTextAlign(Align.LEFT);
      paint.setTextSize(renderer.getLegendTextSize());
      int sLength = Math.min(titles.length, renderer.getSeriesRendererCount());
      for (int i = 0; i < sLength; i++) {
        final float lineSize = getLegendShapeWidth(i);
        String text = titles[i];
        if (titles.length == renderer.getSeriesRendererCount()) {
          paint.setColor(renderer.getSeriesRendererAt(i).getColor());
        } else {
          paint.setColor(Color.LTGRAY);
        }
        float[] widths = new float[text.length()];
        paint.getTextWidths(text, widths);
        float sum = 0;
        for (float value : widths) {
          sum += value;
        }
        float extraSize = lineSize + 10 + sum;
        float currentWidth = currentX + extraSize;

        if (i > 0 && getExceed(currentWidth, renderer, right, width)) {
          currentX = left;
          currentY += renderer.getLegendTextSize();
          size += renderer.getLegendTextSize();
          currentWidth = currentX + extraSize;
        }
        if (getExceed(currentWidth, renderer, right, width)) {
          float maxWidth = right - currentX - lineSize - 10;
          if (isVertical(renderer)) {
            maxWidth = width - currentX - lineSize - 10;
          }
          int nr = paint.breakText(text, true, maxWidth, widths);
          text = text.substring(0, nr) + "...";
        }
        if (!calculate) {
          drawLegendShape(canvas, renderer.getSeriesRendererAt(i), currentX, currentY, i, paint);
          drawString(canvas, text, currentX + lineSize + 5, currentY + 5, paint);
        }
        currentX += extraSize;
      }
    }
    return Math.round(size + renderer.getLegendTextSize());
  }

  /**
   * Draw a multiple lines string.
   * 
   * @param canvas the canvas to paint to
   * @param text the text to be painted
   * @param x the x value of the area to draw to
   * @param y the y value of the area to draw to
   * @param paint the paint to be used for drawing
   */
  protected void drawString(Canvas canvas, String text, float x, float y, Paint paint) {
    String[] lines = text.split("\n");
    Rect rect = new Rect();
    int yOff = 0;
    for (int i = 0; i < lines.length; ++i) {
      canvas.drawText(lines[i], x, y + yOff, paint);
      paint.getTextBounds(lines[i], 0, lines[i].length(), rect);
      yOff = yOff + rect.height() + 5; // space between lines is 5
    }
  }

  /**
   * Calculates if the current width exceeds the total width.
   * 
   * @param currentWidth the current width
   * @param renderer the renderer
   * @param right the right side pixel value
   * @param width the total width
   * @return if the current width exceeds the total width
   */
  protected boolean getExceed(float currentWidth, DefaultRenderer renderer, int right, int width) {
    boolean exceed = currentWidth > right;
    if (isVertical(renderer)) {
      exceed = currentWidth > width;
    }
    return exceed;
  }

  /**
   * Checks if the current chart is rendered as vertical.
   * 
   * @param renderer the renderer
   * @return if the chart is rendered as a vertical one
   */
  public boolean isVertical(DefaultRenderer renderer) {
    return renderer instanceof XYMultipleSeriesRenderer
        && ((XYMultipleSeriesRenderer) renderer).getOrientation() == Orientation.VERTICAL;
  }
  
  /**
   * Makes sure the fraction digit is not displayed, if not needed.
   * 
   * @param label the input label value
   * @return the label without the useless fraction digit
   */
  protected String getLabel(double label) {
    String text = "";
    if (label == Math.round(label)) {
      text = Math.round(label) + "";
    } else {
      text = label + "";
    }
    return text;
  }

  private static float[] calculateDrawPoints(float p1x, float p1y, float p2x, float p2y,
      int screenHeight, int screenWidth) {
    float drawP1x;
    float drawP1y;
    float drawP2x;
    float drawP2y;

    if (p1y > screenHeight) {
      // Intersection with the top of the screen
      float m = (p2y - p1y) / (p2x - p1x);
      drawP1x = (screenHeight - p1y + m * p1x) / m;
      drawP1y = screenHeight;

      if (drawP1x < 0) {
        // If Intersection is left of the screen we calculate the intersection
        // with the left border
        drawP1x = 0;
        drawP1y = p1y - m * p1x;
      } else if (drawP1x > screenWidth) {
        // If Intersection is right of the screen we calculate the intersection
        // with the right border
        drawP1x = screenWidth;
        drawP1y = m * screenWidth + p1y - m * p1x;
      }
    } else if (p1y < 0) {
      float m = (p2y - p1y) / (p2x - p1x);
      drawP1x = (-p1y + m * p1x) / m;
      drawP1y = 0;
      if (drawP1x < 0) {
        drawP1x = 0;
        drawP1y = p1y - m * p1x;
      } else if (drawP1x > screenWidth) {
        drawP1x = screenWidth;
        drawP1y = m * screenWidth + p1y - m * p1x;
      }
    } else {
      // If the point is in the screen use it
      drawP1x = p1x;
      drawP1y = p1y;
    }

    if (p2y > screenHeight) {
      float m = (p2y - p1y) / (p2x - p1x);
      drawP2x = (screenHeight - p1y + m * p1x) / m;
      drawP2y = screenHeight;
      if (drawP2x < 0) {
        drawP2x = 0;
        drawP2y = p1y - m * p1x;
      } else if (drawP2x > screenWidth) {
        drawP2x = screenWidth;
        drawP2y = m * screenWidth + p1y - m * p1x;
      }
    } else if (p2y < 0) {
      float m = (p2y - p1y) / (p2x - p1x);
      drawP2x = (-p1y + m * p1x) / m;
      drawP2y = 0;
      if (drawP2x < 0) {
        drawP2x = 0;
        drawP2y = p1y - m * p1x;
      } else if (drawP2x > screenWidth) {
        drawP2x = screenWidth;
        drawP2y = m * screenWidth + p1y - m * p1x;
      }
    } else {
      // If the point is in the screen use it
      drawP2x = p2x;
      drawP2y = p2y;
    }

    return new float[] { drawP1x, drawP1y, drawP2x, drawP2y };
  }

  /**
   * The graphical representation of a path.
   * 
   * @param canvas the canvas to paint to
   * @param points the points that are contained in the path to paint
   * @param paint the paint to be used for painting
   * @param circular if the path ends with the start point
   */
  protected void drawPath(Canvas canvas, float[] points, Paint paint, boolean circular) {
    Path path = new Path();
    int height = canvas.getHeight();
    int width = canvas.getWidth();

    float[] tempDrawPoints;
    if (points.length < 4) {
      return;
    }
    tempDrawPoints = calculateDrawPoints(points[0], points[1], points[2], points[3], height, width);
    path.moveTo(tempDrawPoints[0], tempDrawPoints[1]);
    path.lineTo(tempDrawPoints[2], tempDrawPoints[3]);

    for (int i = 4; i < points.length; i += 2) {
      if ((points[i - 1] < 0 && points[i + 1] < 0)
          || (points[i - 1] > height && points[i + 1] > height)) {
        continue;
      }
      tempDrawPoints = calculateDrawPoints(points[i - 2], points[i - 1], points[i], points[i + 1],
          height, width);
      if (!circular) {
        path.moveTo(tempDrawPoints[0], tempDrawPoints[1]);
      }
      path.lineTo(tempDrawPoints[2], tempDrawPoints[3]);
    }
    if (circular) {
      path.lineTo(points[0], points[1]);
    }
    canvas.drawPath(path, paint);
  }

  /**
   * Returns the legend shape width.
   * 
   * @param seriesIndex the series index
   * @return the legend shape width
   */
  public abstract int getLegendShapeWidth(int seriesIndex);

  /**
   * The graphical representation of the legend shape.
   * 
   * @param canvas the canvas to paint to
   * @param renderer the series renderer
   * @param x the x value of the point the shape should be drawn at
   * @param y the y value of the point the shape should be drawn at
   * @param seriesIndex the series index
   * @param paint the paint to be used for drawing
   */
  public abstract void drawLegendShape(Canvas canvas, SimpleSeriesRenderer renderer, float x,
      float y, int seriesIndex, Paint paint);

  /**
   * Calculates the best text to fit into the available space.
   * 
   * @param text the entire text
   * @param width the width to fit the text into
   * @param paint the paint
   * @return the text to fit into the space
   */
  private String getFitText(String text, float width, Paint paint) {
    String newText = text;
    int length = text.length();
    int diff = 0;
    while (paint.measureText(newText) > width && diff < length) {
      diff++;
      newText = text.substring(0, length - diff) + "...";
    }
    if (diff == length) {
      newText = "...";
    }
    return newText;
  }

  /**
   * Calculates the current legend size.
   * 
   * @param renderer the renderer
   * @param defaultHeight the default height
   * @param extraHeight the added extra height
   * @return the legend size
   */
  protected int getLegendSize(DefaultRenderer renderer, int defaultHeight, float extraHeight) {
    int legendSize = renderer.getLegendHeight();
    if (renderer.isShowLegend() && legendSize == 0) {
      legendSize = defaultHeight;
    }
    if (!renderer.isShowLegend() && renderer.isShowLabels()) {
      legendSize = (int) (renderer.getLabelsTextSize() * 4 / 3 + extraHeight);
    }
    return legendSize;
  }

  /**
   * Draws a text label.
   * 
   * @param canvas the canvas
   * @param labelText the label text
   * @param renderer the renderer
   * @param prevLabelsBounds the previous rendered label bounds
   * @param centerX the round chart center on X axis
   * @param centerY the round chart center on Y axis
   * @param shortRadius the short radius for the round chart
   * @param longRadius the long radius for the round chart
   * @param currentAngle the current angle
   * @param angle the label extra angle
   * @param left the left side
   * @param right the right side
   * @param color the label color
   * @param paint the paint
   * @param line if a line to the label should be drawn
   */
  protected void drawLabel(Canvas canvas, String labelText, DefaultRenderer renderer,
      List<RectF> prevLabelsBounds, int centerX, int centerY, float shortRadius, float longRadius,
      float currentAngle, float angle, int left, int right, int color, Paint paint, boolean line) {
    if (renderer.isShowLabels()) {
      paint.setColor(color);
      double rAngle = Math.toRadians(90 - (currentAngle + angle / 2));
      double sinValue = Math.sin(rAngle);
      double cosValue = Math.cos(rAngle);
      int x1 = Math.round(centerX + (float) (shortRadius * sinValue));
      int y1 = Math.round(centerY + (float) (shortRadius * cosValue));
      int x2 = Math.round(centerX + (float) (longRadius * sinValue));
      int y2 = Math.round(centerY + (float) (longRadius * cosValue));

      float size = renderer.getLabelsTextSize();
      float extra = Math.max(size / 2, 10);
      paint.setTextAlign(Align.LEFT);
      if (x1 > x2) {
        extra = -extra;
        paint.setTextAlign(Align.RIGHT);
      }
      float xLabel = x2 + extra;
      float yLabel = y2;
      float width = right - xLabel;
      if (x1 > x2) {
        width = xLabel - left;
      }
      labelText = getFitText(labelText, width, paint);
      float widthLabel = paint.measureText(labelText);
      boolean okBounds = false;
      while (!okBounds && line) {
        boolean intersects = false;
        int length = prevLabelsBounds.size();
        for (int j = 0; j < length && !intersects; j++) {
          RectF prevLabelBounds = prevLabelsBounds.get(j);
          if (prevLabelBounds.intersects(xLabel, yLabel, xLabel + widthLabel, yLabel + size)) {
            intersects = true;
            yLabel = Math.max(yLabel, prevLabelBounds.bottom);
          }
        }
        okBounds = !intersects;
      }

      if (line) {
        y2 = (int) (yLabel - size / 2);
        canvas.drawLine(x1, y1, x2, y2, paint);
        canvas.drawLine(x2, y2, x2 + extra, y2, paint);
      } else {
        paint.setTextAlign(Align.CENTER);
      }
      canvas.drawText(labelText, xLabel, yLabel, paint);
      if (line) {
        prevLabelsBounds.add(new RectF(xLabel, yLabel, xLabel + widthLabel, yLabel + size));
      }
    }
  }

  public boolean isNullValue(double value) {
    return Double.isNaN(value) || Double.isInfinite(value) || value == MathHelper.NULL_VALUE;
  }

  /**
   * Given screen coordinates, returns the series and point indexes of a chart
   * element. If there is no chart element (line, point, bar, etc) at those
   * coordinates, null is returned.
   * 
   * @param screenPoint
   * @return the series and point indexes
   */
  public SeriesSelection getSeriesAndPointForScreenCoordinate(Point screenPoint) {
    return null;
  }

}




Java Source Code List

org.achartengine.ChartFactory.java
org.achartengine.GraphicalActivity.java
org.achartengine.GraphicalView.java
org.achartengine.ITouchHandler.java
org.achartengine.TouchHandlerOld.java
org.achartengine.TouchHandler.java
org.achartengine.chart.AbstractChart.java
org.achartengine.chart.BarChart.java
org.achartengine.chart.BubbleChart.java
org.achartengine.chart.ClickableArea.java
org.achartengine.chart.CombinedXYChart.java
org.achartengine.chart.CubicLineChart.java
org.achartengine.chart.DialChart.java
org.achartengine.chart.DoughnutChart.java
org.achartengine.chart.LineChart.java
org.achartengine.chart.PieChart.java
org.achartengine.chart.PieMapper.java
org.achartengine.chart.PieSegment.java
org.achartengine.chart.PointStyle.java
org.achartengine.chart.RangeBarChart.java
org.achartengine.chart.RangeStackedBarChart.java
org.achartengine.chart.RoundChart.java
org.achartengine.chart.ScatterChart.java
org.achartengine.chart.TimeChart.java
org.achartengine.chart.XYChart.java
org.achartengine.model.CategorySeries.java
org.achartengine.model.MultipleCategorySeries.java
org.achartengine.model.Point.java
org.achartengine.model.RangeCategorySeries.java
org.achartengine.model.SeriesSelection.java
org.achartengine.model.TimeSeries.java
org.achartengine.model.XYMultipleSeriesDataset.java
org.achartengine.model.XYSeries.java
org.achartengine.model.XYValueSeries.java
org.achartengine.renderer.BasicStroke.java
org.achartengine.renderer.DefaultRenderer.java
org.achartengine.renderer.DialRenderer.java
org.achartengine.renderer.SimpleSeriesRenderer.java
org.achartengine.renderer.XYMultipleSeriesRenderer.java
org.achartengine.renderer.XYSeriesRenderer.java
org.achartengine.tools.AbstractTool.java
org.achartengine.tools.FitZoom.java
org.achartengine.tools.PanListener.java
org.achartengine.tools.Pan.java
org.achartengine.tools.ZoomEvent.java
org.achartengine.tools.ZoomListener.java
org.achartengine.tools.Zoom.java
org.achartengine.util.IndexXYMap.java
org.achartengine.util.MathHelper.java
org.achartengine.util.XYEntry.java
org.flexlabs.widgets.dualbattery.BatteryApplication.java
org.flexlabs.widgets.dualbattery.BatteryLevel.java
org.flexlabs.widgets.dualbattery.BatteryWidget1x1.java
org.flexlabs.widgets.dualbattery.BatteryWidget2x2.java
org.flexlabs.widgets.dualbattery.BatteryWidget3x4.java
org.flexlabs.widgets.dualbattery.BatteryWidgetUpdater.java
org.flexlabs.widgets.dualbattery.BatteryWidget.java
org.flexlabs.widgets.dualbattery.BillingObserver.java
org.flexlabs.widgets.dualbattery.Constants.java
org.flexlabs.widgets.dualbattery.app.AboutFragment.java
org.flexlabs.widgets.dualbattery.app.BatteryHistoryActivity.java
org.flexlabs.widgets.dualbattery.app.DonateFragment.java
org.flexlabs.widgets.dualbattery.app.FeedbackFragment.java
org.flexlabs.widgets.dualbattery.app.SettingsActivity.java
org.flexlabs.widgets.dualbattery.app.SettingsContainer.java
org.flexlabs.widgets.dualbattery.app.SettingsFragment.java
org.flexlabs.widgets.dualbattery.service.BootUpReceiver.java
org.flexlabs.widgets.dualbattery.service.IntentReceiver.java
org.flexlabs.widgets.dualbattery.service.MonitorService.java
org.flexlabs.widgets.dualbattery.service.NotificationManager.java
org.flexlabs.widgets.dualbattery.storage.BatteryLevelAdapter.java
org.flexlabs.widgets.dualbattery.ui.IntegerListPreference.java
org.flexlabs.widgets.dualbattery.ui.PreferenceListFragment.java
org.flexlabs.widgets.dualbattery.ui.SeekBarPreference.java
org.flexlabs.widgets.dualbattery.widgetsettings.BatteryInfoFragment.java
org.flexlabs.widgets.dualbattery.widgetsettings.PropertiesFragment.java
org.flexlabs.widgets.dualbattery.widgetsettings.WidgetActivity.java
org.flexlabs.widgets.dualbattery.widgetsettings.WidgetSettingsContainer.java