summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/ui/CacheBarView.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/ui/CacheBarView.java')
-rw-r--r--src/com/android/gallery3d/ui/CacheBarView.java270
1 files changed, 270 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/ui/CacheBarView.java b/src/com/android/gallery3d/ui/CacheBarView.java
new file mode 100644
index 000000000..40f84d8f9
--- /dev/null
+++ b/src/com/android/gallery3d/ui/CacheBarView.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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 com.android.gallery3d.ui;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.app.GalleryActivity;
+import com.android.gallery3d.util.Future;
+import com.android.gallery3d.util.FutureListener;
+import com.android.gallery3d.util.ThreadPool.Job;
+import com.android.gallery3d.util.ThreadPool.JobContext;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Message;
+import android.os.StatFs;
+import android.text.format.Formatter;
+import android.view.View.MeasureSpec;
+
+import java.io.File;
+
+public class CacheBarView extends GLView implements TextButton.OnClickedListener {
+ private static final String TAG = "CacheBarView";
+ private static final int FONT_COLOR = 0xffffffff;
+ private static final int MSG_REFRESH_STORAGE = 1;
+ private static final int PIN_SIZE = 36;
+
+ public interface Listener {
+ void onDoneClicked();
+ }
+
+ private GalleryActivity mActivity;
+ private Context mContext;
+
+ private StorageInfo mStorageInfo;
+ private long mUserChangeDelta;
+ private Future<StorageInfo> mStorageInfoFuture;
+ private Handler mHandler;
+
+ private int mTotalHeight;
+ private int mPinLeftMargin;
+ private int mPinRightMargin;
+ private int mButtonRightMargin;
+
+ private NinePatchTexture mBackground;
+ private GLView mLeftPin; // The pin icon.
+ private GLView mLeftLabel; // "Make available offline"
+ private ProgressBar mStorageBar;
+ private Label mStorageLabel; // "27.26 GB free"
+ private TextButton mDoneButton; // "Done"
+
+ private Listener mListener;
+
+ public CacheBarView(GalleryActivity activity, int resBackground, int height,
+ int pinLeftMargin, int pinRightMargin, int buttonRightMargin,
+ int fontSize) {
+ mActivity = activity;
+ mContext = activity.getAndroidContext();
+
+ mPinLeftMargin = pinLeftMargin;
+ mPinRightMargin = pinRightMargin;
+ mButtonRightMargin = buttonRightMargin;
+
+ mBackground = new NinePatchTexture(mContext, resBackground);
+ Rect paddings = mBackground.getPaddings();
+
+ // The total height of the strip that includes the bar containing Pin,
+ // Label, DoneButton, ..., ect. and the extended fading bar.
+ mTotalHeight = height + paddings.top;
+
+ mLeftPin = new Icon(mContext, R.drawable.ic_manage_pin, PIN_SIZE, PIN_SIZE);
+ mLeftLabel = new Label(mContext, R.string.make_available_offline,
+ fontSize, FONT_COLOR);
+ addComponent(mLeftPin);
+ addComponent(mLeftLabel);
+
+ mDoneButton = new TextButton(mContext, R.string.done);
+ mDoneButton.setOnClickListener(this);
+ NinePatchTexture normal = new NinePatchTexture(
+ mContext, R.drawable.btn_default_normal_holo_dark);
+ NinePatchTexture pressed = new NinePatchTexture(
+ mContext, R.drawable.btn_default_pressed_holo_dark);
+ mDoneButton.setNormalBackground(normal);
+ mDoneButton.setPressedBackground(pressed);
+ addComponent(mDoneButton);
+
+ // Initially the progress bar and label are invisible.
+ // It will be made visible after we have the storage information.
+ mStorageBar = new ProgressBar(mContext,
+ R.drawable.progress_primary_holo_dark,
+ R.drawable.progress_secondary_holo_dark,
+ R.drawable.progress_bg_holo_dark);
+ mStorageLabel = new Label(mContext, "", 14, Color.WHITE);
+ addComponent(mStorageBar);
+ addComponent(mStorageLabel);
+ mStorageBar.setVisibility(GLView.INVISIBLE);
+ mStorageLabel.setVisibility(GLView.INVISIBLE);
+
+ mHandler = new SynchronizedHandler(activity.getGLRoot()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_REFRESH_STORAGE:
+ mStorageInfo = (StorageInfo) msg.obj;
+ refreshStorageInfo();
+ break;
+ }
+ }
+ };
+ }
+
+ public void setListener(Listener listener) {
+ mListener = listener;
+ }
+
+ // Called by mDoneButton
+ public void onClicked(GLView source) {
+ if (mListener != null) {
+ mListener.onDoneClicked();
+ }
+ }
+
+ @Override
+ protected void onLayout(
+ boolean changed, int left, int top, int right, int bottom) {
+ // The size of mStorageLabel can change, so we need to layout
+ // even if the size of CacheBarView does not change.
+ int w = right - left;
+ int h = bottom - top;
+
+ mLeftPin.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+ int pinH = mLeftPin.getMeasuredHeight();
+ int pinW = mLeftPin.getMeasuredWidth();
+ int pinT = (h - pinH) / 2;
+ int pinL = mPinLeftMargin;
+ mLeftPin.layout(pinL, pinT, pinL + pinW, pinT + pinH);
+
+ mLeftLabel.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+ int labelH = mLeftLabel.getMeasuredHeight();
+ int labelW = mLeftLabel.getMeasuredWidth();
+ int labelT = (h - labelH) / 2;
+ int labelL = pinL + pinW + mPinRightMargin;
+ mLeftLabel.layout(labelL, labelT, labelL + labelW, labelT + labelH);
+
+ mDoneButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+ int doneH = mDoneButton.getMeasuredHeight();
+ int doneW = mDoneButton.getMeasuredWidth();
+ int doneT = (h - doneH) / 2;
+ int doneR = w - mButtonRightMargin;
+ mDoneButton.layout(doneR - doneW, doneT, doneR, doneT + doneH);
+
+ int centerX = w / 2;
+ int centerY = h / 2;
+
+ int capBarH = 20;
+ int capBarW = 200;
+ int capBarT = centerY - capBarH / 2;
+ int capBarL = centerX - capBarW / 2;
+ mStorageBar.layout(capBarL, capBarT, capBarL + capBarW,
+ capBarT + capBarH);
+
+ mStorageLabel.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+ int capLabelH = mStorageLabel.getMeasuredHeight();
+ int capLabelW = mStorageLabel.getMeasuredWidth();
+ int capLabelT = centerY - capLabelH / 2;
+ int capLabelL = centerX + capBarW / 2 + 8;
+ mStorageLabel.layout(capLabelL , capLabelT, capLabelL + capLabelW,
+ capLabelT + capLabelH);
+ }
+
+ public void refreshStorageInfo() {
+ long used = mStorageInfo.usedBytes;
+ long total = mStorageInfo.totalBytes;
+ long cached = mStorageInfo.usedCacheBytes;
+ long target = mStorageInfo.targetCacheBytes;
+
+ double primary = (double) used / total;
+ double secondary =
+ (double) (used - cached + target + mUserChangeDelta) / total;
+
+ mStorageBar.setProgress((int) (primary * 10000));
+ mStorageBar.setSecondaryProgress((int) (secondary * 10000));
+
+ long freeBytes = mStorageInfo.totalBytes - mStorageInfo.usedBytes;
+ String sizeString = Formatter.formatFileSize(mContext, freeBytes);
+ String label = mContext.getString(R.string.free_space_format, sizeString);
+ mStorageLabel.setText(label);
+ mStorageBar.setVisibility(GLView.VISIBLE);
+ mStorageLabel.setVisibility(GLView.VISIBLE);
+ requestLayout(); // because the size of the label may have changed.
+ }
+
+ public void increaseTargetCacheSize(long delta) {
+ mUserChangeDelta += delta;
+ refreshStorageInfo();
+ }
+
+ @Override
+ protected void renderBackground(GLCanvas canvas) {
+ Rect paddings = mBackground.getPaddings();
+ mBackground.draw(canvas, 0, -paddings.top, getWidth(), mTotalHeight);
+ }
+
+ public void resume() {
+ mStorageInfoFuture = mActivity.getThreadPool().submit(
+ new StorageInfoJob(),
+ new FutureListener<StorageInfo>() {
+ public void onFutureDone(Future<StorageInfo> future) {
+ mStorageInfoFuture = null;
+ if (!future.isCancelled()) {
+ mHandler.sendMessage(mHandler.obtainMessage(
+ MSG_REFRESH_STORAGE, future.get()));
+ }
+ }
+ });
+ }
+
+ public void pause() {
+ if (mStorageInfoFuture != null) {
+ mStorageInfoFuture.cancel();
+ mStorageInfoFuture = null;
+ }
+ mStorageBar.setVisibility(GLView.INVISIBLE);
+ mStorageLabel.setVisibility(GLView.INVISIBLE);
+ }
+
+ public static class StorageInfo {
+ long totalBytes; // number of bytes the storage has.
+ long usedBytes; // number of bytes already used.
+ long usedCacheBytes; // number of bytes used for the cache (should be less
+ // then usedBytes).
+ long targetCacheBytes;// number of bytes used for the cache
+ // if all pending downloads (and removals) are completed.
+ }
+
+ private class StorageInfoJob implements Job<StorageInfo> {
+ public StorageInfo run(JobContext jc) {
+ File cacheDir = mContext.getExternalCacheDir();
+ if (cacheDir == null) {
+ cacheDir = mContext.getCacheDir();
+ }
+ String path = cacheDir.getAbsolutePath();
+ StatFs stat = new StatFs(path);
+ long blockSize = stat.getBlockSize();
+ long availableBlocks = stat.getAvailableBlocks();
+ long totalBlocks = stat.getBlockCount();
+ StorageInfo si = new StorageInfo();
+ si.totalBytes = blockSize * totalBlocks;
+ si.usedBytes = blockSize * (totalBlocks - availableBlocks);
+ si.usedCacheBytes = mActivity.getDataManager().getTotalUsedCacheSize();
+ si.targetCacheBytes = mActivity.getDataManager().getTotalTargetCacheSize();
+ return si;
+ }
+ }
+}