/*
* This file is part of Oekaki Mobile.
* Copyright (C) 2013 Jeremy Lam
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package idv.jlchntoz.oekakimobile;
import java.util.*;
import android.content.Context;
import android.graphics.*;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.*;
public class ColorPaletteSelector extends View {
OnSelectedListener Listener;
ArrayList<Integer> Colors;
final EventHandler _evh;
int width, height, targetH;
float posX, posY;
final int blockSize;
int _a, _b;
Paint p;
public interface OnSelectedListener {
public void OnSelected(int index, int color);
public int OnReplace(int index);
}
public ColorPaletteSelector(Context context, AttributeSet attrs) {
super(context, attrs);
_evh = new EventHandler();
blockSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
30, context.getResources().getDisplayMetrics());
Colors = new ArrayList<Integer>();
p = new Paint();
setClickable(true);
setLongClickable(true);
setOnClickListener(_evh);
setOnLongClickListener(_evh);
setOnTouchListener(_evh);
targetH = blockSize * 2 + 1;
invalidate();
}
@Override
protected void onSizeChanged(int w, int h, int ow, int oh) {
width = w;
height = h;
invalidate();
}
@Override
protected void onDraw(Canvas c) {
c.drawColor(Color.TRANSPARENT);
_a = _b = 0;
boolean extraHeight = false;
for (int i = 0; i < Colors.size(); i++) {
if (_a + blockSize > width) {
_a = 0;
_b += blockSize;
}
p.setStyle(Style.FILL);
p.setColor(getColor(i));
c.drawRect(_a, _b, _a + blockSize, _b + blockSize, p);
p.setStyle(Style.STROKE);
p.setColor(Color.GRAY);
c.drawRect(_a, _b, _a + blockSize, _b + blockSize, p);
_a += blockSize;
}
while (_a + blockSize < width || !extraHeight) {
p.setStyle(Style.STROKE);
p.setColor(Color.GRAY);
c.drawRect(_a, _b, _a + blockSize, _b + blockSize, p);
_a += blockSize;
if (!extraHeight && _a + blockSize > width) {
extraHeight = true;
_a = 0;
_b += blockSize;
}
}
if (_b + blockSize + 1 > height) {
targetH = _b + blockSize + 1;
requestLayout();
}
}
@Override
protected void onMeasure(int w, int h) {
int widthSize = MeasureSpec.getSize(w);
int heightSize = MeasureSpec.getSize(h);
int mh;
switch (MeasureSpec.getMode(h)) {
case MeasureSpec.EXACTLY:
mh = heightSize;
case MeasureSpec.AT_MOST:
mh = Math.min(targetH, heightSize);
break;
default:
mh = targetH;
break;
}
setMeasuredDimension(widthSize, mh);
}
public void setListener(OnSelectedListener Listener) {
this.Listener = Listener;
}
public void setColor(int index, int color) {
while (index >= Colors.size())
Colors.add(Color.TRANSPARENT);
Colors.set(index, color);
invalidate();
}
public int getColor(int index) {
return Colors.get(index);
}
private int getIndexByPosition(float x, float y) {
int widthFixed = (int) Math.floor(width / blockSize);
x = (float) Math.floor(x / blockSize);
y = (float) Math.floor(y / blockSize);
int index = (int) (y * widthFixed + x);
if (x > widthFixed)
return -1;
return index;
}
private class EventHandler implements OnLongClickListener, OnTouchListener,
OnClickListener {
@Override
public void onClick(View v) {
if (v != ColorPaletteSelector.this)
return;
int index = getIndexByPosition(posX, posY);
if (index >= 0 && index < Colors.size() && Listener != null)
Listener.OnSelected(index, Colors.get(index));
}
@Override
public boolean onLongClick(View v) {
if (v != ColorPaletteSelector.this)
return false;
int index = getIndexByPosition(posX, posY);
if (index >= 0 && Listener != null) {
setColor(index, Listener.OnReplace(index));
ColorPaletteSelector.this.invalidate();
return true;
}
return false;
}
@Override
public boolean onTouch(View v, MotionEvent e) {
if (v != ColorPaletteSelector.this)
return false;
posX = e.getX();
posY = e.getY();
return false;
}
}
}