/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* This file is part of FileExplorer.
*
* FileExplorer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FileExplorer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with SwiFTP. If not, see <http://www.gnu.org/licenses/>.
*/
package net.micode.fileexplorer;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class CategoryBar extends View {
private static final String LOG_TAG = "CategoryBar";
private static final int MARGIN = 12;
private static final int ANI_TOTAL_FRAMES = 10;
private static final int ANI_PERIOD = 100;
private Timer timer;
private class Category {
public long value;
public long tmpValue; // used for animation
public long aniStep; // animation step
public int resImg;
}
private ArrayList<Category> categories = new ArrayList<Category>();
private long mFullValue;
public void setFullValue(long value) {
mFullValue = value;
}
public CategoryBar(Context context) {
this(context, null);
}
public CategoryBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CategoryBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void addCategory(int categoryImg) {
Category ca = new Category();
ca.resImg = categoryImg;
categories.add(ca);
}
public boolean setCategoryValue(int index, long value) {
if (index < 0 || index >= categories.size())
return false;
categories.get(index).value = value;
invalidate();
return true;
}
@Override
protected void onDraw(Canvas canvas) {
Drawable d = getDrawable(R.drawable.category_bar_empty);
int width = getWidth() - MARGIN * 2;
int height = getHeight() - MARGIN * 2;
boolean isHorizontal = (width > height);
Rect bounds = null;
if ( isHorizontal )
bounds = new Rect(MARGIN, 0, MARGIN + width, d.getIntrinsicHeight());
else
bounds = new Rect(0, MARGIN, d.getIntrinsicWidth(), MARGIN + height);
int beginning = MARGIN;
if ( !isHorizontal ) beginning += height;
d.setBounds(bounds);
d.draw(canvas);
if (mFullValue != 0) {
for (Category c : categories) {
long value = (timer == null ? c.value : c.tmpValue);
if ( isHorizontal ) {
int w = (int) (value * width / mFullValue);
if (w == 0)
continue;
bounds.left = beginning;
bounds.right = beginning + w;
d = getDrawable(c.resImg);
bounds.bottom = bounds.top + d.getIntrinsicHeight();
d.setBounds(bounds);
d.draw(canvas);
beginning += w;
}
else {
int h = (int) (value * height / mFullValue);
if (h == 0)
continue;
bounds.bottom = beginning;
bounds.top = beginning - h;
d = getDrawable(c.resImg);
bounds.right = bounds.left + d.getIntrinsicWidth();
d.setBounds(bounds);
d.draw(canvas);
beginning -= h;
}
}
}
if ( isHorizontal ) {
bounds.left = 0;
bounds.right = bounds.left + getWidth();
}
else {
bounds.top = 0;
bounds.bottom = bounds.top + getHeight();
}
d = getDrawable(R.drawable.category_bar_mask);
d.setBounds(bounds);
d.draw(canvas);
}
private Drawable getDrawable(int id) {
return getContext().getResources().getDrawable(id);
}
private void stepAnimation() {
if (timer == null)
return;
int finished = 0;
for (Category c : categories) {
c.tmpValue += c.aniStep;
if (c.tmpValue >= c.value) {
c.tmpValue = c.value;
finished++;
if (finished >= categories.size()) {
// stop animation
timer.cancel();
timer = null;
Log.v(LOG_TAG, "Animation stopped");
break;
}
}
}
postInvalidate();
}
synchronized public void startAnimation() {
if (timer != null) {
return;
}
Log.v(LOG_TAG, "startAnimation");
for (Category c : categories) {
c.tmpValue = 0;
c.aniStep = c.value / ANI_TOTAL_FRAMES;
}
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
stepAnimation();
}
}, 0, ANI_PERIOD);
}
}