diff options
Diffstat (limited to 'src/com/cyanogenmod/filemanager/ui/widgets/DiskUsageGraph.java')
-rw-r--r-- | src/com/cyanogenmod/filemanager/ui/widgets/DiskUsageGraph.java | 343 |
1 files changed, 223 insertions, 120 deletions
diff --git a/src/com/cyanogenmod/filemanager/ui/widgets/DiskUsageGraph.java b/src/com/cyanogenmod/filemanager/ui/widgets/DiskUsageGraph.java index ecd0cfa0..bdae373c 100644 --- a/src/com/cyanogenmod/filemanager/ui/widgets/DiskUsageGraph.java +++ b/src/com/cyanogenmod/filemanager/ui/widgets/DiskUsageGraph.java @@ -17,20 +17,22 @@ package com.cyanogenmod.filemanager.ui.widgets; import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.RectF; +import android.graphics.*; import android.util.AttributeSet; import android.view.View; - +import android.widget.Toast; +import com.cyanogenmod.filemanager.R; import com.cyanogenmod.filemanager.model.DiskUsage; +import com.cyanogenmod.filemanager.model.DiskUsageCategory; import com.cyanogenmod.filemanager.ui.ThemeManager; import com.cyanogenmod.filemanager.ui.ThemeManager.Theme; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; /** * A class that display graphically the usage of a mount point. @@ -38,11 +40,62 @@ import java.util.List; public class DiskUsageGraph extends View { /** + * This is a list for accessing the loaded colors + */ + public static final List<Integer> COLOR_LIST = new ArrayList<Integer>(); + /** + * This is an internal color id reference + */ + private static final List<Integer> INTERNAL_COLOR_LIST = new ArrayList<Integer>() { + { + + // Material Blue + add(R.color.material_palette_blue_1); + add(R.color.material_palette_blue_2); + add(R.color.material_palette_blue_3); + add(R.color.material_palette_blue_4); + + // Material Lime + add(R.color.material_palette_green_1); + add(R.color.material_palette_green_2); + add(R.color.material_palette_green_3); + add(R.color.material_palette_green_4); + + // Material Orange + add(R.color.material_palette_orange_1); + add(R.color.material_palette_orange_2); + add(R.color.material_palette_orange_3); + add(R.color.material_palette_orange_4); + + // Material Pink + add(R.color.material_palette_pink_1); + add(R.color.material_palette_pink_2); + add(R.color.material_palette_pink_3); + add(R.color.material_palette_pink_4); + + + } + }; + + /** + * Initialize the color assets into memory for direct access + */ + private void initializeColors() { + // Only load the colors if needed + if (COLOR_LIST.size() == 0) { + for (int colorId : INTERNAL_COLOR_LIST) { + COLOR_LIST.add(getContext().getResources().getColor(colorId)); + } + } + } + + /** * @hide */ int mDiskWarningAngle = (360 * 95) / 100; - private AnimationDrawingThread mThread; + private static String sWarningText; + /** * @hide */ @@ -50,12 +103,18 @@ public class DiskUsageGraph extends View { Collections.synchronizedList(new ArrayList<DiskUsageGraph.DrawingObject>(2)); /** + * @hide + * drawing objects lock + */ + static final int[] LOCK = new int[0]; + + /** * Constructor of <code>DiskUsageGraph</code>. * * @param context The current context */ public DiskUsageGraph(Context context) { - super(context); + this(context, null); } /** @@ -65,7 +124,7 @@ public class DiskUsageGraph extends View { * @param attrs The attributes of the XML tag that is inflating the view. */ public DiskUsageGraph(Context context, AttributeSet attrs) { - super(context, attrs); + this(context, attrs, 0); } /** @@ -80,6 +139,10 @@ public class DiskUsageGraph extends View { */ public DiskUsageGraph(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + initializeColors(); + if (sWarningText == null) { + sWarningText = context.getResources().getString(R.string.pref_disk_usage_warning_level); + } } /** @@ -94,8 +157,8 @@ public class DiskUsageGraph extends View { } /** - * Method that sets the free disk space percentage after the widget change his color - * to advise the user + * Method that sets the free disk space percentage after the widget change his color to advise + * the user * * @param percentage The free disk space percentage */ @@ -103,22 +166,32 @@ public class DiskUsageGraph extends View { this.mDiskWarningAngle = (360 * percentage) / 100; } + // Handle thread for drawing calculations + private Future mAnimationFuture = null; + private static ExecutorService sThreadPool = Executors.newFixedThreadPool(1); + /** * Method that draw the disk usage. * - * @param diskUsage The disk usage + * @param diskUsage {@link com.cyanogenmod.filemanager.model.DiskUsage} The disk usage params */ public void drawDiskUsage(DiskUsage diskUsage) { + // Clear if a current drawing exit - if (this.mThread != null) { - this.mThread.exit(); + if (mAnimationFuture != null && !mAnimationFuture.isCancelled()) { + mAnimationFuture.cancel(true); + } + + // Clear canvas + synchronized (LOCK) { + this.mDrawingObjects.clear(); } - this.mDrawingObjects.clear(); invalidate(); // Start drawing thread - this.mThread = new AnimationDrawingThread(diskUsage); - this.mThread.start(); + AnimationDrawingRunnable animationDrawingRunnable = new AnimationDrawingRunnable(diskUsage); + mAnimationFuture = sThreadPool.submit(animationDrawingRunnable); + } /** @@ -130,32 +203,116 @@ public class DiskUsageGraph extends View { super.onDraw(canvas); //Draw all the drawing objects - int cc = this.mDrawingObjects.size(); - for (int i = 0; i < cc; i++) { - DrawingObject dwo = this.mDrawingObjects.get(i); - canvas.drawArc(dwo.mRectF, dwo.mStartAngle, dwo.mSweepAngle, false, dwo.mPaint); + synchronized (LOCK) { + for (DrawingObject dwo : this.mDrawingObjects) { + canvas.drawArc(dwo.mRectF, dwo.mStartAngle, dwo.mSweepAngle, false, dwo.mPaint); + } } } /** * A thread for drawing the animation of the graph. */ - private class AnimationDrawingThread extends Thread { + private class AnimationDrawingRunnable implements Runnable { private final DiskUsage mDiskUsage; - private boolean mRunning; - private final Object mSync = new Object(); - private int mIndex = 0; + + // Delay in between UI updates and slow down calculations + private static final long ANIMATION_DELAY = 1l; + + // Slop space adjustment for space between segments + private static final int SLOP = 2; + + // flags + private static final boolean USE_COLORS = true; /** * Constructor of <code>AnimationDrawingThread</code>. * * @param diskUsage The disk usage */ - public AnimationDrawingThread(DiskUsage diskUsage) { - super(); + public AnimationDrawingRunnable(DiskUsage diskUsage) { this.mDiskUsage = diskUsage; - this.mRunning = false; + } + + private void sleepyTime() { + try { + Thread.sleep(ANIMATION_DELAY); + } catch (InterruptedException ignored) { + } + } + + private void redrawCanvas() { + //Redraw the canvas + post(new Runnable() { + @Override + public void run() { + invalidate(); + } + }); + } + + private void drawTotal(Rect rect, int stroke) { + // Draw total + DrawingObject drawingObject = createDrawingObject(rect, "disk_usage_total_color", + stroke); + synchronized (LOCK) { + mDrawingObjects.add(drawingObject); + } + while (drawingObject.mSweepAngle < 360) { + drawingObject.mSweepAngle++; + redrawCanvas(); + sleepyTime(); + } + } + + private void drawUsed(Rect rect, int stroke, float used) { + // Draw used + DrawingObject drawingObject = createDrawingObject(rect, "disk_usage_used_color", stroke); + synchronized (LOCK) { + mDrawingObjects.add(drawingObject); + } + while (drawingObject.mSweepAngle < used) { + drawingObject.mSweepAngle++; + redrawCanvas(); + sleepyTime(); + } + } + + private void drawUsedWithColors(Rect rect, int stroke) { + // Draw used segments + if (mDiskUsage != null) { + int lastSweepAngle = 0; + float catUsed = 100.0f; + int color; + int index = 0; + for (DiskUsageCategory category : mDiskUsage.getUsageCategoryList()) { + catUsed = (category.getSizeBytes() * 100) / mDiskUsage.getTotal(); // calc percent + catUsed = (catUsed < 1) ? 1 : catUsed; // Normalize + catUsed = (360 * catUsed) / 100; // calc angle + + // Figure out a color + if (index > -1 && index < COLOR_LIST.size()) { + color = COLOR_LIST.get(index); + index++; + } else { + index = 0; + color = COLOR_LIST.get(index); + } + + DrawingObject drawingObject = createDrawingObjectNoTheme(rect, color, stroke); + drawingObject.mStartAngle += lastSweepAngle; + synchronized (LOCK) { + mDrawingObjects.add(drawingObject); + } + while (drawingObject.mSweepAngle < catUsed + SLOP) { + drawingObject.mSweepAngle++; + redrawCanvas(); + sleepyTime(); + } + lastSweepAngle += drawingObject.mSweepAngle - SLOP; + } + } } /** @@ -172,108 +329,27 @@ public class DiskUsageGraph extends View { rect.top += stroke / 2; rect.bottom -= stroke / 2; - float used = 0.0f; - if (this.mDiskUsage == null) { - used = 100.0f; - } else if (this.mDiskUsage.getTotal() != 0) { + float used = 100.0f; + if (this.mDiskUsage != null && this.mDiskUsage.getTotal() != 0) { used = (this.mDiskUsage.getUsed() * 100) / this.mDiskUsage.getTotal(); } //Translate to angle used = (360 * used) / 100; - synchronized (this.mSync) { - this.mRunning = true; - } - try { - boolean disk_warning = false; - while (this.mRunning) { - //Get the current arc - DrawingObject dwo = null; - if (DiskUsageGraph.this.mDrawingObjects != null - && DiskUsageGraph.this.mDrawingObjects.size() > this.mIndex) { - dwo = DiskUsageGraph.this.mDrawingObjects.get(this.mIndex); - } - - //Draw the total arc circle and then the used arc circle - if (this.mIndex == 0 && dwo == null) { - //Initialize the total arc circle - DiskUsageGraph.this.mDrawingObjects.add( - createDrawingObject( - rect, "disk_usage_total_color", stroke)); //$NON-NLS-1$ - continue; - } - if (this.mIndex == 1 && dwo == null) { - //Initialize the used arc circle - DiskUsageGraph.this.mDrawingObjects.add( - createDrawingObject( - rect, "disk_usage_used_color", stroke)); //$NON-NLS-1$ - continue; - } + // Draws out the graph background color + drawTotal(rect, stroke); - if (this.mIndex == 1 && !disk_warning && - dwo.mSweepAngle >= DiskUsageGraph.this.mDiskWarningAngle) { - Theme theme = ThemeManager.getCurrentTheme(getContext()); - dwo.mPaint.setColor( - theme.getColor( - getContext(), - "disk_usage_used_warning_color")); //$NON-NLS-1$ - disk_warning = true; - } - - //Redraw the canvas - post(new Runnable() { - @Override - public void run() { - invalidate(); - } - }); - - //Next draw call - dwo.mSweepAngle++; - if (this.mIndex >= 1) { - //Only fill until used - if ((dwo.mSweepAngle >= used) || (this.mIndex > 1)) { - synchronized (this.mSync) { - break; //End of the animation - } - } - } - if (dwo.mSweepAngle == 360) { - this.mIndex++; - } - - try { - Thread.sleep(1L); - } catch (Throwable ex) { - /**NON BLOCK**/ - } - } - } finally { - try { - synchronized (this.mSync) { - this.mRunning = false; - this.mSync.notify(); - } - } catch (Throwable ex) { - /**NON BLOCK**/ - } + // Draw the usage + if (USE_COLORS) { + drawUsedWithColors(rect, stroke); + } else { + drawUsed(rect, stroke, used); } - } - /** - * Method that force the thread to exit. - */ - public void exit() { - try { - synchronized (this.mSync) { - if (this.mRunning) { - this.mRunning = false; - this.mSync.wait(); - } - } - } catch (Throwable ex) { - /**NON BLOCK**/ + if (used >= mDiskWarningAngle) { + Toast.makeText(getContext(), sWarningText, Toast.LENGTH_SHORT).show(); } + } /** @@ -282,6 +358,7 @@ public class DiskUsageGraph extends View { * @param rect The area of drawing * @param colorResourceThemeId The theme resource identifier of the color * @param stroke The stroke width + * * @return DrawingObject The drawing object */ private DrawingObject createDrawingObject( @@ -297,6 +374,31 @@ public class DiskUsageGraph extends View { out.mRectF = new RectF(rect); return out; } + + /** + * Method that creates the drawing object. + * + * @param rect The area of drawing + * @param color Integer id of the color + * @param stroke The stroke width + * + * @return DrawingObject The drawing object + * + * [TODO][MSB]: Implement colors for sections into theme + */ + @Deprecated + private DrawingObject createDrawingObjectNoTheme( + Rect rect, int color, int stroke) { + DrawingObject out = new DrawingObject(); + out.mSweepAngle = 0; + out.mPaint.setColor(color); + out.mPaint.setStrokeWidth(stroke); + out.mPaint.setAntiAlias(true); + out.mPaint.setStrokeCap(Paint.Cap.BUTT); + out.mPaint.setStyle(Paint.Style.STROKE); + out.mRectF = new RectF(rect); + return out; + } } /** @@ -304,6 +406,7 @@ public class DiskUsageGraph extends View { */ private class DrawingObject { DrawingObject() {/**NON BLOCK**/} + int mStartAngle = -180; int mSweepAngle = 0; Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); |