package com.xtremelabs.robolectric.shadows; import android.graphics.*; import com.xtremelabs.robolectric.internal.Implementation; import com.xtremelabs.robolectric.internal.Implements; import java.util.ArrayList; import java.util.List; import static com.xtremelabs.robolectric.Robolectric.newInstanceOf; import static com.xtremelabs.robolectric.Robolectric.shadowOf; /** * Shadows the {@code android.graphics.Canvas} class. *

* Broken. * This implementation is very specific to the application for which it was developed. * Todo: Reimplement. Consider using the same strategy of collecting a history of draw events and providing methods for writing queries based on type, number, and order of events. */ @SuppressWarnings({"UnusedDeclaration"}) @Implements(Canvas.class) public class ShadowCanvas { private List pathPaintEvents = new ArrayList(); private List circlePaintEvents = new ArrayList(); private Paint drawnPaint; private Bitmap targetBitmap = newInstanceOf(Bitmap.class); private float translateX; private float translateY; private float scaleX = 1; private float scaleY = 1; public void __constructor__(Bitmap bitmap) { this.targetBitmap = bitmap; } public void appendDescription(String s) { shadowOf(targetBitmap).appendDescription(s); } public String getDescription() { return shadowOf(targetBitmap).getDescription(); } @Implementation public void translate(float x, float y) { this.translateX = x; this.translateY = y; } @Implementation public void scale(float sx, float sy) { this.scaleX = sx; this.scaleY = sy; } @Implementation public void scale(float sx, float sy, float px, float py) { this.scaleX = sx; this.scaleY = sy; } @Implementation public void drawPaint(Paint paint) { drawnPaint = paint; } @Implementation public void drawColor(int color) { appendDescription("draw color " + color); } @Implementation public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { describeBitmap(bitmap, paint); int x = (int) (left + translateX); int y = (int) (top + translateY); if (x != 0 && y != 0) { appendDescription(" at (" + x + "," + y + ")"); } if (scaleX != 1 && scaleY != 1) { appendDescription(" scaled by (" + scaleX + "," + scaleY + ")"); } } @Implementation public void drawPath(Path path, Paint paint) { pathPaintEvents.add(new PathPaintHistoryEvent(path, paint)); separateLines(); appendDescription("Path " + shadowOf(path).getPoints().toString()); } private void describeBitmap(Bitmap bitmap, Paint paint) { separateLines(); appendDescription(shadowOf(bitmap).getDescription()); if (paint != null) { ColorFilter colorFilter = paint.getColorFilter(); if (colorFilter != null) { appendDescription(" with " + colorFilter); } } } private void separateLines() { if (getDescription().length() != 0) { appendDescription("\n"); } } @Implementation public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { describeBitmap(bitmap, paint); appendDescription(" transformed by matrix"); } public int getPathPaintHistoryCount() { return pathPaintEvents.size(); } public int getCirclePaintHistoryCount() { return circlePaintEvents.size(); } public boolean hasDrawnPath() { return getPathPaintHistoryCount() > 0; } public boolean hasDrawnCircle() { return circlePaintEvents.size() > 0; } public Paint getDrawnPathPaint(int i) { return pathPaintEvents.get(i).pathPaint; } public Path getDrawnPath(int i) { return pathPaintEvents.get(i).drawnPath; } public CirclePaintHistoryEvent getDrawnCircle(int i) { return circlePaintEvents.get(i); } public void resetCanvasHistory() { pathPaintEvents.clear(); circlePaintEvents.clear(); } public Paint getDrawnPaint() { return drawnPaint; } private static class PathPaintHistoryEvent { private Path drawnPath; private Paint pathPaint; PathPaintHistoryEvent(Path drawnPath, Paint pathPaint) { this.drawnPath = drawnPath; this.pathPaint = pathPaint; } } public static class CirclePaintHistoryEvent { public Paint paint; public float centerX; public float centerY; public float radius; private CirclePaintHistoryEvent(float centerX, float centerY, float radius, Paint paint) { this.paint = paint; this.centerX = centerX; this.centerY = centerY; this.radius = radius; } } }