diff --git a/HoloGraphLibrary/res/drawable-xhdpi/popup_black.9.png b/HoloGraphLibrary/res/drawable-xhdpi/popup_black.9.png old mode 100644 new mode 100755 index 4da6a2c..47815f4 Binary files a/HoloGraphLibrary/res/drawable-xhdpi/popup_black.9.png and b/HoloGraphLibrary/res/drawable-xhdpi/popup_black.9.png differ diff --git a/HoloGraphLibrary/src/com/echo/holographlibrary/Bar.java b/HoloGraphLibrary/src/com/echo/holographlibrary/Bar.java old mode 100644 new mode 100755 index 1e4b05d..6ee5452 --- a/HoloGraphLibrary/src/com/echo/holographlibrary/Bar.java +++ b/HoloGraphLibrary/src/com/echo/holographlibrary/Bar.java @@ -27,8 +27,7 @@ import android.graphics.Region; public class Bar { - - private int color; + private int color = -1; private String name; private float value; private Path path; diff --git a/HoloGraphLibrary/src/com/echo/holographlibrary/BarGraph.java b/HoloGraphLibrary/src/com/echo/holographlibrary/BarGraph.java old mode 100644 new mode 100755 index f2a8750..19a81ab --- a/HoloGraphLibrary/src/com/echo/holographlibrary/BarGraph.java +++ b/HoloGraphLibrary/src/com/echo/holographlibrary/BarGraph.java @@ -24,18 +24,23 @@ package com.echo.holographlibrary; import android.content.Context; -import android.graphics.*; +import android.graphics.Bitmap; import android.graphics.Bitmap.Config; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Region; import android.graphics.drawable.NinePatchDrawable; import android.util.AttributeSet; import android.view.MotionEvent; -import android.view.View; -import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -public class BarGraph extends View { - +public class BarGraph extends Graph { private ArrayList points = new ArrayList(); private Paint p = new Paint(); private Path path = new Path(); @@ -45,7 +50,7 @@ public class BarGraph extends View { private OnBarClickedListener listener; private Bitmap fullImage; private boolean shouldUpdate = false; - private String unit = "$"; + private String unit = ""; private Boolean append = false; private Rect r2 = new Rect(); private Rect r3 = new Rect(); @@ -64,6 +69,7 @@ public void setShowBarText(boolean show) { public void setBars(ArrayList points) { this.points = points; + shouldUpdate = true; postInvalidate(); } @@ -96,26 +102,25 @@ public void onDraw(Canvas ca) { NinePatchDrawable popup = (NinePatchDrawable) this.getResources().getDrawable(R.drawable.popup_black); float maxValue = 0; - float padding = 7; - int selectPadding = 4; - float bottomPadding = 40; + float padding = convertToPx(7, DP); + int selectPadding = (int) convertToPx(4, DP); + float bottomPadding = convertToPx(40, DP); float usableHeight; if (showBarText) { - this.p.setTextSize(40); - this.p.getTextBounds(unit, 0, 1, r3); - usableHeight = getHeight() - bottomPadding - Math.abs(r3.top - r3.bottom) - 26; + this.p.setTextSize(convertToPx(20, SP)); + this.p.getTextBounds(unit+"1", 0, unit.length()+1, r3); + usableHeight = getHeight() - bottomPadding - Math.abs(r3.top - r3.bottom) - convertToPx(30, DP); } else { usableHeight = getHeight() - bottomPadding; } - p.setColor(Color.BLACK); - p.setStrokeWidth(2); + p.setStrokeWidth(convertToPx(2, DP)); p.setAlpha(50); p.setAntiAlias(true); - canvas.drawLine(0, getHeight() - bottomPadding + 10, getWidth(), getHeight() - bottomPadding + 10, p); + canvas.drawLine(0, getHeight() - bottomPadding + convertToPx(10, DP), getWidth(), getHeight() - bottomPadding + convertToPx(10, DP), p); float barWidth = (getWidth() - (padding * 2) * points.size()) / points.size(); @@ -135,22 +140,21 @@ public void onDraw(Canvas ca) { p.setPath(path); p.setRegion(new Region(r.left - selectPadding, r.top - selectPadding, r.right + selectPadding, r.bottom + selectPadding)); - this.p.setColor(p.getColor()); + this.p.setColor(p.getColor() == -1 ? DEFAULT_COLORS.get(count % DEFAULT_COLORS.size()) : p.getColor()); this.p.setAlpha(255); canvas.drawRect(r, this.p); - this.p.setTextSize(20); - canvas.drawText(p.getName(), (int) (((r.left + r.right) / 2) - (this.p.measureText(p.getName()) / 2)), getHeight() - 5, this.p); + this.p.setTextSize(convertToPx(20, SP)); + canvas.drawText(p.getName(), (int) (((r.left + r.right) / 2) - (this.p.measureText(p.getName()) / 2)), getHeight() - convertToPx(5, DP), this.p); if (showBarText) { - this.p.setTextSize(40); + this.p.setTextSize(convertToPx(20, SP)); this.p.setColor(Color.WHITE); this.p.getTextBounds(unit + p.getValue(), 0, 1, r2); - if (popup != null) - popup.setBounds((int) (((r.left + r.right) / 2) - (this.p.measureText(unit + p.getValue()) / 2)) - 14, r.top + (r2.top - r2.bottom) - 26, (int) (((r.left + r.right) / 2) + (this.p.measureText(unit + p.getValue()) / 2)) + 14, r.top); + popup.setBounds((int) (((r.left + r.right) / 2) - (this.p.measureText(unit + p.getValue()) / 2)) - (int) convertToPx(14, DP), r.top + (r2.top - r2.bottom) - (int) convertToPx(30, DP), (int) (((r.left + r.right) / 2) + (this.p.measureText(unit + p.getValue()) / 2)) + (int) convertToPx(14, DP), r.top); popup.draw(canvas); if (isAppended()) - canvas.drawText(p.getValue() + unit, (int) (((r.left + r.right) / 2) - (this.p.measureText(unit + p.getValue()) / 2)), r.top - 20, this.p); + canvas.drawText(p.getValue() + unit, (int) (((r.left + r.right) / 2) - (this.p.measureText(unit + p.getValue()) / 2)), r.top - convertToPx(20, DP), this.p); else - canvas.drawText(unit + p.getValue(), (int) (((r.left + r.right) / 2) - (this.p.measureText(unit + p.getValue()) / 2)), r.top - 20, this.p); + canvas.drawText(unit + p.getValue(), (int) (((r.left + r.right) / 2) - (this.p.measureText(unit + p.getValue()) / 2)), r.top - convertToPx(20, DP), this.p); } if (indexSelected == count && listener != null) { this.p.setColor(Color.parseColor("#33B5E5")); @@ -168,7 +172,7 @@ public void onDraw(Canvas ca) { } @Override - public boolean onTouchEvent(@NotNull MotionEvent event) { + public boolean onTouchEvent(MotionEvent event) { Point point = new Point(); point.x = (int) event.getX(); diff --git a/HoloGraphLibrary/src/com/echo/holographlibrary/Graph.java b/HoloGraphLibrary/src/com/echo/holographlibrary/Graph.java new file mode 100644 index 0000000..d0a5691 --- /dev/null +++ b/HoloGraphLibrary/src/com/echo/holographlibrary/Graph.java @@ -0,0 +1,27 @@ +package com.echo.holographlibrary; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; + +import java.util.Arrays; +import java.util.List; + +class Graph extends View { + static final List DEFAULT_COLORS = Arrays.asList(0xffcc5c57, 0xff5f6ec2, 0xfff9db00, 0xffb7cf47, 0xfff48935, 0xff4ba5e2, 0xff99cc00, 0xffffbb33, 0xffaa66cc); + static final int DP = TypedValue.COMPLEX_UNIT_DIP; + static final int SP = TypedValue.COMPLEX_UNIT_SP; + + public Graph(Context context){ + super(context); + } + + public Graph(Context context, AttributeSet attrs) { + super(context, attrs); + } + + float convertToPx(int value, int unit) { + return TypedValue.applyDimension(unit, value, getContext().getResources().getDisplayMetrics()); + } +} diff --git a/HoloGraphLibrary/src/com/echo/holographlibrary/Line.java b/HoloGraphLibrary/src/com/echo/holographlibrary/Line.java old mode 100644 new mode 100755 diff --git a/HoloGraphLibrary/src/com/echo/holographlibrary/LineGraph.java b/HoloGraphLibrary/src/com/echo/holographlibrary/LineGraph.java old mode 100644 new mode 100755 index 31aac8d..bd8d224 --- a/HoloGraphLibrary/src/com/echo/holographlibrary/LineGraph.java +++ b/HoloGraphLibrary/src/com/echo/holographlibrary/LineGraph.java @@ -24,393 +24,522 @@ package com.echo.holographlibrary; import android.content.Context; -import android.graphics.*; +import android.graphics.Bitmap; import android.graphics.Bitmap.Config; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; import android.graphics.Path.Direction; +import android.graphics.Point; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.Region; import android.util.AttributeSet; import android.view.MotionEvent; -import android.view.View; import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; -public class LineGraph extends View { - - private ArrayList lines = new ArrayList(); - private Paint paint = new Paint(); - private Paint txtPaint = new Paint(); - private float minY = 0, minX = 0; - private float maxY = 0, maxX = 0; - private boolean isMaxYUserSet = false; - private int lineToFill = -1; - private int indexSelected = -1; - private OnPointClickedListener listener; - private Bitmap fullImage; - private boolean shouldUpdate = false; - private boolean showMinAndMax = false; - private boolean showHorizontalGrid = false; - private int gridColor = 0xffffffff; - - public LineGraph(Context context){ - this(context,null); - } - public LineGraph(Context context, AttributeSet attrs) { - super(context, attrs); - txtPaint.setColor(0xffffffff); - txtPaint.setTextSize(20); - txtPaint.setAntiAlias(true); - } - public void setGridColor(int color) - { - gridColor = color; - } - public void showHorizontalGrid(boolean show) - { - showHorizontalGrid = show; - } - public void showMinAndMaxValues(boolean show) - { - showMinAndMax = show; +public class LineGraph extends Graph { + private ArrayList lines = new ArrayList(); + private Paint paint = new Paint(); + private Paint txtPaint = new Paint(); + private Paint numPaint = new Paint(); + private float minY = 0, minX = 0; + private float maxY = 0, maxX = 0; + private boolean isRangeSet = false; + private boolean isDomainSet = false; + private int lineToFill = -1; + private int indexSelected = -1; + private OnPointClickedListener listener; + private Bitmap fullImage; + private boolean shouldUpdate = false; + private int gridColor = 0xffffffff; + private String yAxisTitle = null; + private String xAxisTitle = null; + private boolean showAxisValues = true; + + boolean debug = false; + + public LineGraph(Context context) { + this(context, null); + } + + public LineGraph(Context context, AttributeSet attrs) { + super(context, attrs); + txtPaint.setColor(0xdd000000); + txtPaint.setTextSize(convertToPx(20, SP)); + numPaint.setColor(0xdd000000); + numPaint.setTextSize(convertToPx(16, SP)); + } + + public void setGridColor(int color) { + gridColor = color; + } + + public void showAxisValues(boolean show) { + showAxisValues = show; + } + + public void setTextColor(int color) { + txtPaint.setColor(color); + } + + public void setTextSize(float s) { + txtPaint.setTextSize(s); + } + + public void setYAxisTitle(String title) { + yAxisTitle = title; + } + + public void setXAxisTitle(String title) { + xAxisTitle = title; + } + + public void update() { + shouldUpdate = true; + postInvalidate(); + } + + public void removeAllLines() { + while (lines.size() > 0) { + lines.remove(0); + } + shouldUpdate = true; + postInvalidate(); + } + + public void addLine(Line line) { + lines.add(line); + shouldUpdate = true; + postInvalidate(); + } + + public ArrayList getLines() { + return lines; + } + + public void setLines(ArrayList lines) { + this.lines = lines; + } + + public int getLineToFill() { + return lineToFill; } - public void setTextColor(int color) - { - txtPaint.setColor(color); - } - public void setTextSize(float s) - { - txtPaint.setTextSize(s); - } - public void setMinY(float minY){ - this.minY = minY; - } - - public void update() - { - shouldUpdate = true; - postInvalidate(); - } - public void removeAllLines(){ - while (lines.size() > 0){ - lines.remove(0); - } - shouldUpdate = true; - postInvalidate(); - } - - public void addLine(Line line) { - lines.add(line); - shouldUpdate = true; - postInvalidate(); - } - public ArrayList getLines() { - return lines; - } - public void setLineToFill(int indexOfLine) { - this.lineToFill = indexOfLine; - shouldUpdate = true; - postInvalidate(); - } - public int getLineToFill(){ - return lineToFill; - } - public void setLines(ArrayList lines) { - this.lines = lines; - } - public Line getLine(int index) { - return lines.get(index); - } - public int getSize(){ - return lines.size(); - } - - public void setRangeY(float min, float max) { - minY = min; - maxY = max; - isMaxYUserSet = true; - } - public float getMaxY(){ - if (isMaxYUserSet){ - return maxY; - } else { - maxY = lines.get(0).getPoint(0).getY(); - for (Line line : lines){ - for (LinePoint point : line.getPoints()){ - if (point.getY() > maxY){ - maxY = point.getY(); - } - } - } - return maxY; - } - - } - public float getMinY(){ - if (isMaxYUserSet){ - return minY; - } else { - float min = lines.get(0).getPoint(0).getY(); - for (Line line : lines){ - for (LinePoint point : line.getPoints()){ - if (point.getY() < min) min = point.getY(); - } - } - minY = min; - return minY; - } - } - public float getMaxX(){ - float max = lines.get(0).getPoint(0).getX(); - for (Line line : lines){ - for (LinePoint point : line.getPoints()){ - if (point.getX() > max) max = point.getX(); - } - } - maxX = max; - return maxX; - - } - public float getMinX(){ - float max = lines.get(0).getPoint(0).getX(); - for (Line line : lines){ - for (LinePoint point : line.getPoints()){ - if (point.getX() < max) max = point.getX(); - } - } - maxX = max; - return maxX; - } - - public void onDraw(Canvas ca) { - if (fullImage == null || shouldUpdate) { - fullImage = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); - Canvas canvas = new Canvas(fullImage); - String max = (int)maxY+"";// used to display max - String min = (int)minY+"";// used to display min - paint.reset(); - Path path = new Path(); - - float bottomPadding = 1, topPadding = 0; - float sidePadding = 10; - if (this.showMinAndMax) - sidePadding = txtPaint.measureText(max); - - float usableHeight = getHeight() - bottomPadding - topPadding; - float usableWidth = getWidth() - sidePadding*2; - float lineSpace = usableHeight/10; - - int lineCount = 0; - for (Line line : lines){ - int count = 0; + + public void setLineToFill(int indexOfLine) { + this.lineToFill = indexOfLine; + shouldUpdate = true; + postInvalidate(); + } + + public Line getLine(int index) { + return lines.get(index); + } + + public int getSize() { + return lines.size(); + } + + public void setRange(float min, float max) { + minY = min; + maxY = max; + isRangeSet = true; + } + + public void setDomain(float min, float max) { + minX = min; + maxX = max; + isDomainSet = true; + } + + public float getMaxY() { + if (isRangeSet) return maxY; + + for (Line line : lines) { + for (LinePoint point : line.getPoints()) { + maxY = point.getY(); + break; + } + } + for (Line line : lines) { + for (LinePoint point : line.getPoints()) { + if (point.getY() > maxY) maxY = point.getY(); + } + } + return maxY; + + } + + public float getMinY() { + if (isRangeSet) return minY; + + for (Line line : lines) { + for (LinePoint point : line.getPoints()) { + minY = point.getY(); + break; + } + } + for (Line line : lines) { + for (LinePoint point : line.getPoints()) { + if (point.getY() < minY) minY = point.getY(); + } + } + return minY; + } + + public float getMaxX() { + if(isDomainSet) return maxX; + + for (Line line : lines) { + for (LinePoint point : line.getPoints()) { + maxX = point.getX(); + break; + } + } + for (Line line : lines) { + for (LinePoint point : line.getPoints()) { + if (point.getX() > maxX) maxX = point.getX(); + } + } + return maxX; + + } + + public float getMinX() { + if(isDomainSet) return minX; + + for (Line line : lines) { + for (LinePoint point : line.getPoints()) { + minX = point.getX(); + break; + } + } + for (Line line : lines) { + for (LinePoint point : line.getPoints()) { + if (point.getX() < minX) minX = point.getX(); + } + } + return minX; + } + + public void onDraw(Canvas ca) { + if (fullImage == null || shouldUpdate) { + fullImage = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); + Canvas canvas = new Canvas(fullImage); + getMaxY(); + getMinY(); + getMaxX(); + getMinX(); + paint.reset(); + Path path = new Path(); + + float topPadding = 0, bottomPadding = 0, leftPadding = 0, rightPadding = 0; + if (showAxisValues) { + bottomPadding = leftPadding = numPaint.getTextSize() * 2f; + rightPadding = numPaint.measureText(maxX+"") / 2; + topPadding = numPaint.measureText(maxY+"") / 2; + } + + float usableHeight = getHeight() - bottomPadding - topPadding; + float usableWidth = getWidth() - leftPadding - rightPadding; + + if(debug) { + txtPaint.setColor(0xffff0000); + canvas.drawRect(0, 0, getWidth(), getHeight(), txtPaint); + txtPaint.setColor(0xff00ff00); + canvas.drawRect(leftPadding, topPadding, usableWidth + leftPadding, usableHeight + topPadding, txtPaint); + txtPaint.setColor(0xdd000000); + } + + int lineCount = 0; + for (Line line : lines) { + int count = 0; float lastXPixels = 0, newYPixels; float lastYPixels = 0, newXPixels; - float maxY = getMaxY(); - float minY = getMinY(); - float maxX = getMaxX(); - float minX = getMinX(); - - if (lineCount == lineToFill){ - paint.setColor(Color.BLACK); - paint.setAlpha(30); - paint.setStrokeWidth(2); - for (int i = 10; i-getWidth() < getHeight(); i = i+20){ - canvas.drawLine(i, getHeight()-bottomPadding, 0, getHeight()-bottomPadding-i, paint); - } - - paint.reset(); - - paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.CLEAR)); - for (LinePoint p : line.getPoints()){ - float yPercent = (p.getY()-minY)/(maxY - minY); - float xPercent = (p.getX()-minX)/(maxX - minX); - if (count == 0){ - lastXPixels = sidePadding + (xPercent*usableWidth); - lastYPixels = getHeight() - bottomPadding - (usableHeight*yPercent); - path.moveTo(lastXPixels, lastYPixels); - } else { - newXPixels = sidePadding + (xPercent*usableWidth); - newYPixels = getHeight() - bottomPadding - (usableHeight*yPercent); - path.lineTo(newXPixels, newYPixels); - Path pa = new Path(); - pa.moveTo(lastXPixels, lastYPixels); - pa.lineTo(newXPixels, newYPixels); - pa.lineTo(newXPixels, 0); - pa.lineTo(lastXPixels, 0); - pa.close(); - canvas.drawPath(pa, paint); - lastXPixels = newXPixels; - lastYPixels = newYPixels; - } - count++; - } - - path.reset(); - - path.moveTo(0, getHeight()-bottomPadding); - path.lineTo(sidePadding, getHeight()-bottomPadding); - path.lineTo(sidePadding, 0); - path.lineTo(0, 0); - path.close(); - canvas.drawPath(path, paint); - - path.reset(); - - path.moveTo(getWidth(), getHeight()-bottomPadding); - path.lineTo(getWidth()-sidePadding, getHeight()-bottomPadding); - path.lineTo(getWidth()-sidePadding, 0); - path.lineTo(getWidth(), 0); - path.close(); - - canvas.drawPath(path, paint); - - } - - lineCount++; - } - - paint.reset(); - - paint.setColor(this.gridColor); - paint.setAlpha(50); - paint.setAntiAlias(true); - canvas.drawLine(sidePadding, getHeight() - bottomPadding, getWidth(), getHeight()-bottomPadding, paint); - if(this.showHorizontalGrid) - for(int i=1;i<=10;i++) - { - canvas.drawLine(sidePadding, getHeight() - bottomPadding-(i*lineSpace), getWidth(), getHeight()-bottomPadding-(i*lineSpace), paint); - } - paint.setAlpha(255); - - - for (Line line : lines){ - int count = 0; + + if (lineCount == lineToFill) { + paint.setColor(Color.BLACK); + paint.setAlpha(30); + paint.setStrokeWidth(2); + for (int i = (int) convertToPx(5, DP); i - getWidth() < getHeight(); i += convertToPx(10, DP)) { + canvas.drawLine(i, getHeight() - bottomPadding, 0, getHeight() - bottomPadding - i, paint); + } + + paint.reset(); + + paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.CLEAR)); + for (LinePoint p : line.getPoints()) { + float yPercent = (p.getY() - minY) / (maxY - minY); + float xPercent = (p.getX() - minX) / (maxX - minX); + if (count == 0) { + lastXPixels = leftPadding + (xPercent * usableWidth); + lastYPixels = getHeight() - bottomPadding - (usableHeight * yPercent); + path.moveTo(lastXPixels, lastYPixels); + } else { + newXPixels = leftPadding + (xPercent * usableWidth); + newYPixels = getHeight() - bottomPadding - (usableHeight * yPercent); + path.lineTo(newXPixels, newYPixels); + Path pa = new Path(); + pa.moveTo(lastXPixels, lastYPixels); + pa.lineTo(newXPixels, newYPixels); + pa.lineTo(newXPixels, 0); + pa.lineTo(lastXPixels, 0); + pa.close(); + canvas.drawPath(pa, paint); + lastXPixels = newXPixels; + lastYPixels = newYPixels; + } + count++; + } + + path.reset(); + + path.moveTo(0, getHeight() - bottomPadding); + path.lineTo(leftPadding, getHeight() - bottomPadding); + path.lineTo(leftPadding, 0); + path.lineTo(0, 0); + path.close(); + canvas.drawPath(path, paint); + + path.reset(); + + path.moveTo(getWidth(), getHeight() - bottomPadding); + path.lineTo(getWidth() - leftPadding, getHeight() - bottomPadding); + path.lineTo(getWidth() - leftPadding, 0); + path.lineTo(getWidth(), 0); + path.close(); + + canvas.drawPath(path, paint); + + } + + lineCount++; + } + + paint.reset(); + + paint.setColor(this.gridColor); + paint.setAlpha(50); + paint.setAntiAlias(true); + canvas.drawLine(leftPadding, getHeight() - bottomPadding, getWidth(), getHeight() - bottomPadding, paint); + paint.setAlpha(255); + + for (Line line : lines) { + int count = 0; float lastXPixels = 0, newYPixels; float lastYPixels = 0, newXPixels; - float maxY = getMaxY(); - float minY = getMinY(); - float maxX = getMaxX(); - float minX = getMinX(); - - paint.setColor(line.getColor()); - paint.setStrokeWidth(6); - - for (LinePoint p : line.getPoints()){ - float yPercent = (p.getY()-minY)/(maxY - minY); - float xPercent = (p.getX()-minX)/(maxX - minX); - if (count == 0){ - lastXPixels = sidePadding + (xPercent*usableWidth); - lastYPixels = getHeight() - bottomPadding - (usableHeight*yPercent); - } else { - newXPixels = sidePadding + (xPercent*usableWidth); - newYPixels = getHeight() - bottomPadding - (usableHeight*yPercent); - canvas.drawLine(lastXPixels, lastYPixels, newXPixels, newYPixels, paint); - lastXPixels = newXPixels; - lastYPixels = newYPixels; - } - count++; - } - } - - - int pointCount = 0; - - for (Line line : lines){ - float maxY = getMaxY(); - float minY = getMinY(); - float maxX = getMaxX(); - float minX = getMinX(); - - paint.setColor(line.getColor()); - paint.setStrokeWidth(6); - paint.setStrokeCap(Paint.Cap.ROUND); - - if (line.isShowingPoints()){ - for (LinePoint p : line.getPoints()){ - float yPercent = (p.getY()-minY)/(maxY - minY); - float xPercent = (p.getX()-minX)/(maxX - minX); - float xPixels = sidePadding + (xPercent*usableWidth); - float yPixels = getHeight() - bottomPadding - (usableHeight*yPercent); - - paint.setColor(Color.GRAY); - canvas.drawCircle(xPixels, yPixels, 10, paint); - paint.setColor(Color.WHITE); - canvas.drawCircle(xPixels, yPixels, 5, paint); - - Path path2 = new Path(); - path2.addCircle(xPixels, yPixels, 30, Direction.CW); - p.setPath(path2); - p.setRegion(new Region((int)(xPixels-30), (int)(yPixels-30), (int)(xPixels+30), (int)(yPixels+30))); - - if (indexSelected == pointCount && listener != null){ - paint.setColor(Color.parseColor("#33B5E5")); - paint.setAlpha(100); - canvas.drawPath(p.getPath(), paint); - paint.setAlpha(255); - } - - pointCount++; - } - } - } - - shouldUpdate = false; - if (this.showMinAndMax) { - ca.drawText(max, 0, txtPaint.getTextSize(), txtPaint); - ca.drawText(min,0,this.getHeight(),txtPaint); - } - } - - ca.drawBitmap(fullImage, 0, 0, null); - - - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - - Point point = new Point(); - point.x = (int) event.getX(); - point.y = (int) event.getY(); - - int count = 0; - int lineCount = 0; + + paint.setColor(line.getColor()); + paint.setStrokeWidth(convertToPx(3, DP)); + + for (LinePoint p : line.getPoints()) { + float yPercent = (p.getY() - minY) / (maxY - minY); + float xPercent = (p.getX() - minX) / (maxX - minX); + if (count == 0) { + lastXPixels = leftPadding + (xPercent * usableWidth); + lastYPixels = getHeight() - bottomPadding - (usableHeight * yPercent); + } else { + newXPixels = leftPadding + (xPercent * usableWidth); + newYPixels = getHeight() - bottomPadding - (usableHeight * yPercent); + canvas.drawLine(lastXPixels, lastYPixels, newXPixels, newYPixels, paint); + lastXPixels = newXPixels; + lastYPixels = newYPixels; + } + count++; + } + } + + int pointCount = 0; + + for (Line line : lines) { + paint.setColor(line.getColor()); + paint.setStrokeWidth(convertToPx(6, DP)); + paint.setStrokeCap(Paint.Cap.ROUND); + + if (line.isShowingPoints()) { + for (LinePoint p : line.getPoints()) { + float yPercent = (p.getY() - minY) / (maxY - minY); + float xPercent = (p.getX() - minX) / (maxX - minX); + float xPixels = leftPadding + (xPercent * usableWidth); + float yPixels = getHeight() - bottomPadding - (usableHeight * yPercent); + + paint.setColor(Color.GRAY); + canvas.drawCircle(xPixels, yPixels, convertToPx(6, DP), paint); + paint.setColor(Color.WHITE); + canvas.drawCircle(xPixels, yPixels, convertToPx(3, DP), paint); + + Path path2 = new Path(); + path2.addCircle(xPixels, yPixels, convertToPx(30, DP), Direction.CW); + p.setPath(path2); + p.setRegion(new Region((int) (xPixels - convertToPx(30, DP)), (int) (yPixels - convertToPx(30, DP)), (int) (xPixels + convertToPx(30, DP)), (int) (yPixels + convertToPx(30, DP)))); + + if (indexSelected == pointCount && listener != null) { + paint.setColor(Color.parseColor("#33B5E5")); + paint.setAlpha(100); + canvas.drawPath(p.getPath(), paint); + paint.setAlpha(255); + } + + pointCount++; + } + } + } + + if (showAxisValues) { + int minSize = (int) convertToPx(50, DP); + + // Find unique integers to display on the x axis + List values = new LinkedList(); + int prevNum = Integer.MIN_VALUE; + int numbersToShow = (int) usableWidth / minSize + 1; + float step = (maxX - minX) / (numbersToShow - 1); + for(int i=0; i(); + prevNum = Integer.MIN_VALUE; + numbersToShow = (int) usableHeight / minSize + 1; + step = (maxY - minY) / (numbersToShow - 1); + for(int i=0; i slices = new ArrayList(); - private Paint paint = new Paint(); - private Path path = new Path(); - - private int indexSelected = -1; - private int thickness = 50; - private OnSliceClickedListener listener; - - - public PieGraph(Context context) { - super(context); - } - public PieGraph(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void onDraw(Canvas canvas) { - canvas.drawColor(Color.TRANSPARENT); - paint.reset(); - paint.setAntiAlias(true); - float midX, midY, radius, innerRadius; - path.reset(); - - float currentAngle = 270; +public class PieGraph extends Graph { + private ArrayList slices = new ArrayList(); + private Paint paint = new Paint(); + private Path path = new Path(); + private Paint textPaint = new Paint(); + private boolean showKey = true; + + private int indexSelected = -1; + private int thickness = (int) convertToPx(25, DP); + private OnSliceClickedListener listener; + + float padding = convertToPx(2, DP); + float keyPadding = convertToPx(5, DP); + float keyOffsetLeft = convertToPx(15, DP); + float keyOffsetBottom = convertToPx(15, DP); + + public PieGraph(Context context) { + super(context); + textPaint.setTextSize(convertToPx(20, SP)); + } + + public PieGraph(Context context, AttributeSet attrs) { + super(context, attrs); + textPaint.setTextSize(convertToPx(20, SP)); + } + + public void onDraw(Canvas canvas) { + canvas.drawColor(Color.TRANSPARENT); + paint.reset(); + paint.setAntiAlias(true); + float midX, midY, radius, innerRadius; + path.reset(); + + float currentAngle = 270; float currentSweep; int totalValue = 0; - float padding = 2; - - midX = getWidth()/2; - midY = getHeight()/2; - if (midX < midY){ - radius = midX; - } else { - radius = midY; - } - radius -= padding; - innerRadius = radius - thickness; - - for (PieSlice slice : slices){ - totalValue += slice.getValue(); - } - - int count = 0; - for (PieSlice slice : slices){ - Path p = new Path(); - paint.setColor(slice.getColor()); - currentSweep = (slice.getValue()/totalValue)*(360); - p.arcTo(new RectF(midX-radius, midY-radius, midX+radius, midY+radius), currentAngle+padding, currentSweep - padding); - p.arcTo(new RectF(midX-innerRadius, midY-innerRadius, midX+innerRadius, midY+innerRadius), (currentAngle+padding) + (currentSweep - padding), -(currentSweep-padding)); - p.close(); - - slice.setPath(p); - slice.setRegion(new Region((int)(midX-radius), (int)(midY-radius), (int)(midX+radius), (int)(midY+radius))); - canvas.drawPath(p, paint); - - if (indexSelected == count && listener != null){ - path.reset(); - paint.setColor(slice.getColor()); - paint.setColor(Color.parseColor("#33B5E5")); - paint.setAlpha(100); - - if (slices.size() > 1) { - path.arcTo(new RectF(midX-radius-(padding*2), midY-radius-(padding*2), midX+radius+(padding*2), midY+radius+(padding*2)), currentAngle, currentSweep+padding); - path.arcTo(new RectF(midX-innerRadius+(padding*2), midY-innerRadius+(padding*2), midX+innerRadius-(padding*2), midY+innerRadius-(padding*2)), currentAngle + currentSweep + padding, -(currentSweep + padding)); - path.close(); - } else { - path.addCircle(midX, midY, radius+padding, Direction.CW); - } - - canvas.drawPath(path, paint); - paint.setAlpha(255); - } - - currentAngle = currentAngle+currentSweep; - - count++; - } - - - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - - Point point = new Point(); - point.x = (int) event.getX(); - point.y = (int) event.getY(); - - int count = 0; - for (PieSlice slice : slices){ - Region r = new Region(); - r.setPath(slice.getPath(), slice.getRegion()); + + midX = getWidth() / (showKey ? 4 : 2); + midY = getHeight() / 2; + if (midX < midY) { + radius = midX; + } else { + radius = midY; + } + radius -= padding; + innerRadius = radius - thickness; + + float size = 0; + for (PieSlice slice : slices) { + // Calculate the total value of the pie chart + totalValue += slice.getValue(); + + // Calculate the size of the legend + size = Math.max(size, textPaint.getTextSize() + keyPadding + keyOffsetLeft + textPaint.measureText(slice.getTitle())); + } + + // Translate the canvas so everything is centered + if (showKey) canvas.translate(size / 2, 0); + + int count = 0; + for (PieSlice slice : slices) { + // Draw the slice + Path p = new Path(); + paint.setColor(slice.getColor() == -1 ? DEFAULT_COLORS.get(count % DEFAULT_COLORS.size()) : slice.getColor()); + currentSweep = (slice.getValue() / totalValue) * (360); + p.arcTo(new RectF(midX - radius, midY - radius, midX + radius, midY + radius), currentAngle + padding, currentSweep - padding); + p.arcTo(new RectF(midX - innerRadius, midY - innerRadius, midX + innerRadius, midY + innerRadius), (currentAngle + padding) + (currentSweep - padding), -(currentSweep - padding)); + p.close(); + + slice.setPath(p); + slice.setRegion(new Region((int) (midX - radius), (int) (midY - radius), (int) (midX + radius), (int) (midY + radius))); + canvas.drawPath(p, paint); + + if (indexSelected == count && listener != null) { + path.reset(); + paint.setColor(Color.parseColor("#33B5E5")); + paint.setAlpha(100); + + if (slices.size() > 1) { + path.arcTo(new RectF(midX - radius - (padding * 2), midY - radius - (padding * 2), midX + radius + (padding * 2), midY + radius + (padding * 2)), currentAngle, currentSweep + padding); + path.arcTo(new RectF(midX - innerRadius + (padding * 2), midY - innerRadius + (padding * 2), midX + innerRadius - (padding * 2), midY + innerRadius - (padding * 2)), currentAngle + currentSweep + padding, -(currentSweep + padding)); + path.close(); + } else { + path.addCircle(midX, midY, radius + padding, Direction.CW); + } + + canvas.drawPath(path, paint); + paint.setAlpha(255); + } + + if (showKey) { + // Add key to bottom right + textPaint.setColor(paint.getColor()); + canvas.drawRect(getWidth() / 2 + keyOffsetLeft, getHeight() - keyOffsetBottom - textPaint.getTextSize() - (count * (textPaint.getTextSize() + keyPadding)), getWidth() / 2 + textPaint.getTextSize() + keyOffsetLeft, getHeight() - keyOffsetBottom - (count * (textPaint.getTextSize() + keyPadding)), textPaint); + canvas.drawText(slice.getTitle(), getWidth() / 2 + textPaint.getTextSize() + keyPadding + keyOffsetLeft, getHeight() - keyOffsetBottom - textPaint.getTextSize() / 8 - (count * (textPaint.getTextSize() + keyPadding)), textPaint); + } + + // Increment values + currentAngle = currentAngle + currentSweep; + count++; + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + Point point = new Point(); + point.x = (int) event.getX(); + point.y = (int) event.getY(); + + float size = 0; + for (PieSlice slice : slices) { + // Calculate the size of the legend + size = Math.max(size, textPaint.getTextSize() + keyPadding + keyOffsetLeft + textPaint.measureText(slice.getTitle())); + } + + indexSelected = -1; + int count = 0; + for (PieSlice slice : slices) { + Region r = new Region(); + r.setPath(slice.getPath(), slice.getRegion()); + if (showKey) r.translate((int) size / 2, 0); if (r.contains(point.x, point.y) && event.getAction() == MotionEvent.ACTION_DOWN) { indexSelected = count; - } else if (event.getAction() == MotionEvent.ACTION_UP){ + } else if (event.getAction() == MotionEvent.ACTION_UP) { if (r.contains(point.x, point.y) && listener != null) { - if (indexSelected > -1){ - listener.onClick(indexSelected); - } - indexSelected = -1; - } - - } - count++; - } - - if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP){ - postInvalidate(); - } - - - - return true; - } - - public ArrayList getSlices() { - return slices; - } - public void setSlices(ArrayList slices) { - this.slices = slices; - postInvalidate(); - } - public PieSlice getSlice(int index) { - return slices.get(index); - } - public void addSlice(PieSlice slice) { - this.slices.add(slice); - postInvalidate(); - } - public void setOnSliceClickedListener(OnSliceClickedListener listener) { - this.listener = listener; - } - - public int getThickness() { - return thickness; - } - public void setThickness(int thickness) { - this.thickness = thickness; - postInvalidate(); - } - - public void removeSlices(){ - for (int i = slices.size()-1; i >= 0; i--){ - slices.remove(i); - } - postInvalidate(); - } - - public static interface OnSliceClickedListener { - public abstract void onClick(int index); - } + if (indexSelected > -1) { + listener.onClick(indexSelected); + } + indexSelected = -1; + } + + } + count++; + } + + if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP) { + postInvalidate(); + } + + return true; + } + + public ArrayList getSlices() { + return slices; + } + + public void setSlices(ArrayList slices) { + this.slices = slices; + postInvalidate(); + } + + public PieSlice getSlice(int index) { + return slices.get(index); + } + + public void addSlice(PieSlice slice) { + this.slices.add(slice); + postInvalidate(); + } + + public void setOnSliceClickedListener(OnSliceClickedListener listener) { + this.listener = listener; + } + + public int getThickness() { + return thickness; + } + + public void setThickness(int thickness) { + this.thickness = thickness; + postInvalidate(); + } + + public void removeSlices() { + for (int i = slices.size() - 1; i >= 0; i--) { + slices.remove(i); + } + postInvalidate(); + } + + public void setTextSize(float size) { + textPaint.setTextSize(size); + postInvalidate(); + } + + public void showKey(boolean show) { + showKey = show; + postInvalidate(); + } + + public static interface OnSliceClickedListener { + public abstract void onClick(int index); + } } diff --git a/HoloGraphLibrary/src/com/echo/holographlibrary/PieSlice.java b/HoloGraphLibrary/src/com/echo/holographlibrary/PieSlice.java old mode 100644 new mode 100755 index 8d32d46..21c90c7 --- a/HoloGraphLibrary/src/com/echo/holographlibrary/PieSlice.java +++ b/HoloGraphLibrary/src/com/echo/holographlibrary/PieSlice.java @@ -29,7 +29,7 @@ public class PieSlice { - private int color = Color.BLACK; + private int color = -1; private float value; private String title; private Path path;