1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-24 02:12:15 -05:00
- Ported to the ColorPickerDialog API
- Translated the API and Internals from Indonesian to English
- Moved to use K-9 strings rather than custom strings.

In an ideal world, we should use ambilwarna as an android library
project, like it was intended.
This commit is contained in:
Jesse Vincent 2010-11-08 02:21:32 +00:00
parent d45081abaa
commit 52e2a437fb
10 changed files with 346 additions and 233 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="296dp"
android:layout_height="256dp"
>
<!--
8 dp padding
8dp padding | 240 dp box | 14dp empty | 26dp hue | 8dp padding -> total 296
8 dp padding
v
total 256
-->
<com.fsck.k9.activity.ColorPickerBox
android:id="@+id/colorpicker_viewBox"
android:layout_x="8dp"
android:layout_y="8dp"
android:layout_width="240dp"
android:layout_height="240dp" />
<ImageView
android:id="@+id/colorpicker_viewHue"
android:layout_x="262dp"
android:layout_y="8dp"
android:layout_width="26dp"
android:layout_height="240dp"
android:src="@drawable/colorpicker_hue"
android:scaleType="fitXY" />
<ImageView
android:id="@+id/colorpicker_arrow"
android:layout_x="252dp"
android:layout_y="4dp"
android:layout_width="8dp"
android:layout_height="9dp"
android:src="@drawable/colorpicker_arrow"
android:scaleType="matrix" />
<ImageView
android:id="@+id/colorpicker_spyglass"
android:layout_x="3dp"
android:layout_y="3dp"
android:layout_width="11dp"
android:layout_height="11dp"
android:src="@drawable/colorpicker_spyglass"
android:scaleType="matrix" />
</AbsoluteLayout>

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
>
<include
android:layout_width="296dp"
android:layout_height="256dp"
android:id="@+id/colorpicker_includeChooser"
layout="@layout/colorpicker_chooser" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="8dp"
android:paddingBottom="8dp"
>
<AbsoluteLayout
android:layout_width="200dp"
android:layout_height="40dp"
>
<View
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_x="0dp"
android:layout_y="0dp"
android:id="@+id/colorpicker_colorOld"
android:background="#faa"
/>
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_x="80dp"
android:layout_y="0dp"
android:src="@drawable/colorpicker_menjadi"
/>
<View
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_x="120dp"
android:layout_y="0dp"
android:id="@+id/colorpicker_colorNew"
android:background="#aaf"
/>
</AbsoluteLayout>
</LinearLayout>
</LinearLayout>

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<dimen name="button_minWidth">100sp</dimen> <dimen name="button_minWidth">100sp</dimen>
<dimen name="colorpicker_onedp">1dp</dimen>
</resources> </resources>

View File

@ -0,0 +1,77 @@
/* Sourced from http://code.google.com/p/android-color-picker/source/browse/trunk/AmbilWarna/src/yuku/ambilwarna/AmbilWarnaBox.java?r=1
* On 2010-11-07
* Translated to English, Ported to use the same (inferior) API as the more standard "ColorPickerDialog" and imported into the K-9 namespace by Jesse Vincent
* In an ideal world, we should move to using AmbilWarna as an Android Library Project in the future
* License: Apache 2.0
* Author: yukuku@code.google.com
*/
package com.fsck.k9.activity;
import com.fsck.k9.R;
import android.content.*;
import android.graphics.*;
import android.graphics.Shader.*;
import android.util.*;
import android.view.*;
public class ColorPickerBox extends View
{
Paint paint;
Shader dalam;
Shader luar;
float hue;
float onedp;
float sizeUiDp = 240.f;
float sizeUiPx; // diset di constructor
float[] tmp00 = new float[3];
public ColorPickerBox(Context context)
{
this(context, null);
}
public ColorPickerBox(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public ColorPickerBox(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
onedp = context.getResources().getDimension(R.dimen.colorpicker_onedp);
sizeUiPx = sizeUiDp * onedp;
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if (paint == null)
{
paint = new Paint();
luar = new LinearGradient(0.f, 0.f, 0.f, sizeUiPx, 0xffffffff, 0xff000000, TileMode.CLAMP);
}
tmp00[1] = tmp00[2] = 1.f;
tmp00[0] = hue;
int rgb = Color.HSVToColor(tmp00);
dalam = new LinearGradient(0.f, 0.f, sizeUiPx, 0.f, 0xffffffff, rgb, TileMode.CLAMP);
ComposeShader shader = new ComposeShader(luar, dalam, PorterDuff.Mode.MULTIPLY);
paint.setShader(shader);
canvas.drawRect(0.f, 0.f, sizeUiPx, sizeUiPx, paint);
}
void setHue(float hue)
{
this.hue = hue;
invalidate();
}
}

View File

@ -1,273 +1,197 @@
/* /* Sourced from http://code.google.com/p/android-color-picker/source/browse/trunk/AmbilWarna/src/yuku/ambilwarna/AmbilWarnaDialog.java?r=1
* Copyright (C) 2007 The Android Open Source Project * On 2010-11-07
* * Translated to English, Ported to use the same (inferior) API as the more standard "ColorPickerDialog" and imported into the K-9 namespace by Jesse Vincent
* Licensed under the Apache License, Version 2.0 (the "License"); * In an ideal world, we should move to using AmbilWarna as an Android Library Project in the future
* you may not use this file except in compliance with the License. * License: Apache 2.0
* You may obtain a copy of the License at * Author: yukuku@code.google.com
*
* 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.fsck.k9.activity; package com.fsck.k9.activity;
import com.fsck.k9.R; import com.fsck.k9.R;
import android.os.Bundle; import android.app.AlertDialog;
import android.app.Dialog; import android.content.*;
import android.graphics.Color;
import android.util.Log;
import android.view.*;
import android.widget.*;
import android.content.Context; public class ColorPickerDialog
import android.graphics.*;
import android.view.MotionEvent;
import android.view.View;
public class ColorPickerDialog extends Dialog
{ {
private static final String TAG = ColorPickerDialog.class.getSimpleName();
public interface OnColorChangedListener public interface OnColorChangedListener
{ {
void colorChanged(int color); void colorChanged(int color);
} }
private OnColorChangedListener mListener; AlertDialog dialog;
private int mInitialColor; OnColorChangedListener listener;
View viewHue;
ColorPickerBox viewBox;
ImageView arrow;
View viewColorOld;
View viewColorNew;
ImageView viewSpyglass;
private static class ColorPickerView extends View float onedp;
int colorOld;
int colorNew;
float hue;
float sat;
float val;
float sizeUiDp = 240.f;
float sizeUiPx; // diset di constructor
public ColorPickerDialog(Context context, OnColorChangedListener listener, int color )
{ {
private Paint mPaint; this.listener = listener;
private Paint mCenterPaint; this.colorOld = color;
private final int[] mColors; this.colorNew = color;
private OnColorChangedListener mListener; Color.colorToHSV(color, tmp01);
hue = tmp01[0];
sat = tmp01[1];
val = tmp01[2];
ColorPickerView(Context c, OnColorChangedListener l, int color) onedp = context.getResources().getDimension(R.dimen.colorpicker_onedp);
sizeUiPx = sizeUiDp * onedp;
Log.d(TAG, "onedp = " + onedp + ", sizeUiPx=" + sizeUiPx); //$NON-NLS-1$//$NON-NLS-2$
View view = LayoutInflater.from(context).inflate(R.layout.colorpicker_dialog, null);
viewHue = view.findViewById(R.id.colorpicker_viewHue);
viewBox = (ColorPickerBox) view.findViewById(R.id.colorpicker_viewBox);
arrow = (ImageView) view.findViewById(R.id.colorpicker_arrow);
viewColorOld = view.findViewById(R.id.colorpicker_colorOld);
viewColorNew = view.findViewById(R.id.colorpicker_colorNew);
viewSpyglass = (ImageView) view.findViewById(R.id.colorpicker_spyglass);
placeArrow();
placeSpyglass();
viewBox.setHue(hue);
viewColorOld.setBackgroundColor(color);
viewColorNew.setBackgroundColor(color);
viewHue.setOnTouchListener(new View.OnTouchListener()
{ {
super(c);
mListener = l;
mColors = new int[]
{
0xFF800000, 0xFF800080, 0xFF000080, 0xFF008080, 0xFF008000,
0xFF808000, 0xFF800000
};
Shader s = new SweepGradient(0, 0, mColors, null);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setShader(s);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(32);
mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCenterPaint.setColor(color);
mCenterPaint.setStrokeWidth(5);
}
private boolean mTrackingCenter;
private boolean mHighlightCenter;
@Override @Override
protected void onDraw(Canvas canvas) public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_MOVE
|| event.getAction() == MotionEvent.ACTION_DOWN
|| event.getAction() == MotionEvent.ACTION_UP)
{ {
float r = CENTER_X - mPaint.getStrokeWidth()*0.5f;
canvas.translate(CENTER_X, CENTER_X); float y = event.getY(); // dalam px, bukan dp
if (y < 0.f) y = 0.f;
if (y > sizeUiPx) y = sizeUiPx - 0.001f;
canvas.drawOval(new RectF(-r, -r, r, r), mPaint); hue = 360.f - 360.f / sizeUiPx * y;
canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint); if (hue == 360.f) hue = 0.f;
if (mTrackingCenter) colorNew = calculateColor();
{ // update view
int c = mCenterPaint.getColor(); viewBox.setHue(hue);
mCenterPaint.setStyle(Paint.Style.STROKE); placeArrow();
viewColorNew.setBackgroundColor(colorNew);
if (mHighlightCenter)
{
mCenterPaint.setAlpha(0xFF);
}
else
{
mCenterPaint.setAlpha(0x80);
}
canvas.drawCircle(0, 0,
CENTER_RADIUS + mCenterPaint.getStrokeWidth(),
mCenterPaint);
mCenterPaint.setStyle(Paint.Style.FILL);
mCenterPaint.setColor(c);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
setMeasuredDimension(CENTER_X*2, CENTER_Y*2);
}
private static final int CENTER_X = 100;
private static final int CENTER_Y = 100;
private static final int CENTER_RADIUS = 32;
private int floatToByte(float x)
{
int n = java.lang.Math.round(x);
return n;
}
private int pinToByte(int n)
{
if (n < 0)
{
n = 0;
}
else if (n > 255)
{
n = 255;
}
return n;
}
private int ave(int s, int d, float p)
{
return s + java.lang.Math.round(p *(d - s));
}
private int interpColor(int colors[], float unit)
{
if (unit <= 0)
{
return colors[0];
}
if (unit >= 1)
{
return colors[colors.length - 1];
}
float p = unit * (colors.length - 1);
int i = (int)p;
p -= i;
// now p is just the fractional part [0...1) and i is the index
int c0 = colors[i];
int c1 = colors[i+1];
int a = ave(Color.alpha(c0), Color.alpha(c1), p);
int r = ave(Color.red(c0), Color.red(c1), p);
int g = ave(Color.green(c0), Color.green(c1), p);
int b = ave(Color.blue(c0), Color.blue(c1), p);
return Color.argb(a, r, g, b);
}
private int rotateColor(int color, float rad)
{
float deg = rad * 180 / 3.1415927f;
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
ColorMatrix cm = new ColorMatrix();
ColorMatrix tmp = new ColorMatrix();
cm.setRGB2YUV();
tmp.setRotate(0, deg);
cm.postConcat(tmp);
tmp.setYUV2RGB();
cm.postConcat(tmp);
final float[] a = cm.getArray();
int ir = floatToByte(a[0] * r + a[1] * g + a[2] * b);
int ig = floatToByte(a[5] * r + a[6] * g + a[7] * b);
int ib = floatToByte(a[10] * r + a[11] * g + a[12] * b);
return Color.argb(Color.alpha(color), pinToByte(ir),
pinToByte(ig), pinToByte(ib));
}
private static final float PI = 3.1415926f;
@Override
public boolean onTouchEvent(MotionEvent event)
{
float x = event.getX() - CENTER_X;
float y = event.getY() - CENTER_Y;
boolean inCenter = java.lang.Math.sqrt(x*x + y*y) <= CENTER_RADIUS;
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
mTrackingCenter = inCenter;
if (inCenter)
{
mHighlightCenter = true;
invalidate();
break;
}
case MotionEvent.ACTION_MOVE:
if (mTrackingCenter)
{
if (mHighlightCenter != inCenter)
{
mHighlightCenter = inCenter;
invalidate();
}
}
else
{
float angle = (float)java.lang.Math.atan2(y, x);
// need to turn angle [-PI ... PI] into unit [0....1]
float unit = angle/(2*PI);
if (unit < 0)
{
unit += 1;
}
mCenterPaint.setColor(interpColor(mColors, unit));
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if (mTrackingCenter)
{
if (inCenter)
{
mListener.colorChanged(mCenterPaint.getColor());
}
mTrackingCenter = false; // so we draw w/o halo
invalidate();
}
// Hack to _Always change the center color for now
mListener.colorChanged(mCenterPaint.getColor());
break;
}
return true; return true;
} }
return false;
} }
});
public ColorPickerDialog(Context context, viewBox.setOnTouchListener(new View.OnTouchListener()
OnColorChangedListener listener,
int initialColor)
{ {
super(context);
mListener = listener;
mInitialColor = initialColor;
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) public boolean onTouch(View v, MotionEvent event)
{ {
super.onCreate(savedInstanceState); if (event.getAction() == MotionEvent.ACTION_MOVE
OnColorChangedListener l = new OnColorChangedListener() || event.getAction() == MotionEvent.ACTION_DOWN
|| event.getAction() == MotionEvent.ACTION_UP)
{ {
public void colorChanged(int color)
{
mListener.colorChanged(color);
dismiss();
}
};
setContentView(new ColorPickerView(getContext(), l, mInitialColor)); float x = event.getX(); // dalam px, bukan dp
setTitle(getContext().getString(R.string.choose_color_title)); float y = event.getY(); // dalam px, bukan dp
if (x < 0.f) x = 0.f;
if (x > sizeUiPx) x = sizeUiPx;
if (y < 0.f) y = 0.f;
if (y > sizeUiPx) y = sizeUiPx;
sat = (1.f / sizeUiPx * x);
val = 1.f - (1.f / sizeUiPx * y);
colorNew = calculateColor();
// update view
placeSpyglass();
viewColorNew.setBackgroundColor(colorNew);
return true;
}
return false;
}
});
dialog = new AlertDialog.Builder(context)
.setView(view)
.setPositiveButton(R.string.okay_action, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
if (ColorPickerDialog.this.listener != null)
{
ColorPickerDialog.this.listener.colorChanged(colorNew);
}
}
})
.setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
if (ColorPickerDialog.this.listener != null)
{
}
}
})
.create();
}
@SuppressWarnings("deprecation")
protected void placeArrow()
{
float y = sizeUiPx - (hue * sizeUiPx / 360.f);
if (y == sizeUiPx) y = 0.f;
AbsoluteLayout.LayoutParams layoutParams = (AbsoluteLayout.LayoutParams) arrow.getLayoutParams();
layoutParams.y = (int) (y + 4);
arrow.setLayoutParams(layoutParams);
}
@SuppressWarnings("deprecation")
protected void placeSpyglass()
{
float x = sat * sizeUiPx;
float y = (1.f - val) * sizeUiPx;
AbsoluteLayout.LayoutParams layoutParams = (AbsoluteLayout.LayoutParams) viewSpyglass.getLayoutParams();
layoutParams.x = (int) (x + 3);
layoutParams.y = (int) (y + 3);
viewSpyglass.setLayoutParams(layoutParams);
}
float[] tmp01 = new float[3];
private int calculateColor()
{
tmp01[0] = hue;
tmp01[1] = sat;
tmp01[2] = val;
return Color.HSVToColor(tmp01);
}
public void show()
{
dialog.show();
} }
} }