aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/cyanogenmod/filemanager/ui/widgets/DiskUsageGraph.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/cyanogenmod/filemanager/ui/widgets/DiskUsageGraph.java')
-rw-r--r--src/com/cyanogenmod/filemanager/ui/widgets/DiskUsageGraph.java343
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);