diff --git a/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/AHSVColor.java b/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/AHSVColor.java
index 1b073b8..4a59f45 100644
--- a/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/AHSVColor.java
+++ b/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/AHSVColor.java
@@ -49,6 +49,23 @@ class AHSVColor {
hsv[0] = oldHue;
}
+ /** Set red (0), green (1) or blue (2) color component. */
+ void setRGBComponent(int component, int value) {
+ int c = getARGB();
+ switch (component) {
+ case 0:
+ c = (c & 0xff00ffff) | (value << 16);
+ break;
+ case 1:
+ c = (c & 0xffff00ff) | (value << 8);
+ break;
+ case 2:
+ c = (c & 0xffffff00) | value;
+ break;
+ }
+ setARGB(c);
+ }
+
/** Get hue,sat,val values. */
float[] getHSV() {
return new float[]{hsv[0], hsv[1], hsv[2]};
@@ -63,4 +80,15 @@ class AHSVColor {
int getARGB() {
return Color.HSVToColor(alpha, hsv);
}
+
+ /** Get red (0), green (1), or blue (2) color component. */
+ int getRGBComponent(int component) {
+ int c = getARGB();
+ switch (component) {
+ case 0: return Color.red(c);
+ case 1: return Color.green(c);
+ case 2: return Color.blue(c);
+ default: throw new RuntimeException("Internal error");
+ }
+ }
}
diff --git a/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerDialog.java b/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerDialog.java
index fe74111..5864c68 100644
--- a/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerDialog.java
+++ b/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerDialog.java
@@ -18,10 +18,13 @@ package net.margaritov.preference.colorpicker;
import org.petero.droidfish.R;
+import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.PixelFormat;
import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
import android.widget.LinearLayout;
public class ColorPickerDialog
@@ -32,7 +35,7 @@ public class ColorPickerDialog
View.OnClickListener {
private ColorPickerView mColorPicker;
-
+ private EditText colorCode;
private ColorPickerPanelView mOldColor;
private ColorPickerPanelView mNewColor;
@@ -52,9 +55,7 @@ public class ColorPickerDialog
}
private void init(int color) {
- // To fight color banding.
getWindow().setFormat(PixelFormat.RGBA_8888);
-
setUp(color, color);
}
@@ -71,26 +72,49 @@ public class ColorPickerDialog
+ additionalInfo + "'");
mColorPicker = findViewById(R.id.color_picker_view);
+ colorCode = findViewById(R.id.color_code);
mOldColor = findViewById(R.id.old_color_panel);
mNewColor = findViewById(R.id.new_color_panel);
- ((LinearLayout) mOldColor.getParent()).setPadding(
- Math.round(mColorPicker.getDrawingOffset()),
- 0,
- Math.round(mColorPicker.getDrawingOffset()),
- 0
- );
-
+ int offs = Math.round(mColorPicker.getDrawingOffset());
+ ((LinearLayout) mOldColor.getParent()).setPadding(offs, 0, offs, 0);
+
mOldColor.setOnClickListener(this);
mNewColor.setOnClickListener(this);
mColorPicker.setOnColorChangedListener(this);
mOldColor.setColor(oldColor);
+
+ colorCode.setOnFocusChangeListener((view, hasFocus) -> {
+ if (!hasFocus)
+ applyColorCode();
+ });
+ colorCode.setOnEditorActionListener((v, id, event) -> {
+ colorCode.clearFocus();
+ String ims = Activity.INPUT_METHOD_SERVICE;
+ InputMethodManager imm = (InputMethodManager)getContext().getSystemService(ims);
+ imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ return true;
+ });
+
mColorPicker.setColor(newColor, true);
}
@Override
public void onColorChanged(int color) {
mNewColor.setColor(color);
+ colorCode.setText(String.format("%08x", color));
+ }
+
+ private void applyColorCode() {
+ String txt = colorCode.getText().toString().trim().toLowerCase();
+ if (txt.length() != 8) // Format must be AARRGGBB
+ return;
+ try {
+ long longVal = Long.parseLong(txt, 16);
+ int val = (int)longVal;
+ if (val != mColorPicker.getColor())
+ mColorPicker.setColor(val, true);
+ } catch (NumberFormatException ignore) {}
}
/**
diff --git a/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerPanelView.java b/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerPanelView.java
index 1a48a25..418a8fa 100644
--- a/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerPanelView.java
+++ b/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerPanelView.java
@@ -30,19 +30,18 @@ import android.view.View;
* @author Daniel Nilsson
*/
public class ColorPickerPanelView extends View {
-
/** The width in pixels of the border surrounding the color panel. */
- private final static float BORDER_WIDTH_PX = 1;
+ private final static float BORDER_WIDTH_PX = 1;
private float mDensity = 1f;
- private int mColor = 0xff000000;
+ private int mColor = 0xff000000;
- private Paint mBorderPaint = new Paint();
- private Paint mColorPaint = new Paint();
+ private Paint mBorderPaint = new Paint();
+ private Paint mColorPaint = new Paint();
- private RectF mDrawingRect;
- private RectF mColorRect;
+ private RectF mDrawingRect;
+ private RectF mColorRect;
private AlphaPatternDrawable mAlphaPattern;
@@ -80,37 +79,45 @@ public class ColorPickerPanelView extends View {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
-
+ width = chooseSize(widthMode, width, Math.round(120f * mDensity));
+ height = chooseSize(heightMode, height, 0);
setMeasuredDimension(width, height);
}
+ int chooseSize(int mode, int size, int preferred) {
+ if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY)
+ return size;
+ return preferred; // MeasureSpec.UNSPECIFIED
+ }
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mDrawingRect = new RectF();
- mDrawingRect.left = getPaddingLeft();
+ mDrawingRect.left = getPaddingLeft();
mDrawingRect.right = w - getPaddingRight();
- mDrawingRect.top = getPaddingTop();
+ mDrawingRect.top = getPaddingTop();
mDrawingRect.bottom = h - getPaddingBottom();
setUpColorRect();
}
private void setUpColorRect() {
- final RectF dRect = mDrawingRect;
+ final RectF dRect = mDrawingRect;
- float left = dRect.left + BORDER_WIDTH_PX;
- float top = dRect.top + BORDER_WIDTH_PX;
+ float left = dRect.left + BORDER_WIDTH_PX;
+ float top = dRect.top + BORDER_WIDTH_PX;
float bottom = dRect.bottom - BORDER_WIDTH_PX;
- float right = dRect.right - BORDER_WIDTH_PX;
+ float right = dRect.right - BORDER_WIDTH_PX;
mColorRect = new RectF(left,top, right, bottom);
mAlphaPattern = new AlphaPatternDrawable((int)(5 * mDensity));
-
mAlphaPattern.setBounds(Math.round(mColorRect.left),
Math.round(mColorRect.top),
Math.round(mColorRect.right),
diff --git a/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerView.java b/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerView.java
index f52cd85..e887aea 100644
--- a/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerView.java
+++ b/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/ColorPickerView.java
@@ -18,6 +18,7 @@ package net.margaritov.preference.colorpicker;
import android.annotation.SuppressLint;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.RectF;
@@ -40,6 +41,9 @@ public class ColorPickerView extends View {
/** The height in dp of the alpha panel */
private float ALPHA_PANEL_HEIGHT = 20f;
+ /** The width or height in dp of one of the red/green/blue panels. */
+ private float RGB_PANEL_SIZE = 30f;
+
/** The distance in dp between the different color panels. */
private float PANEL_SPACING = 10f;
@@ -56,9 +60,13 @@ public class ColorPickerView extends View {
/** Distance form the edges of the view of where we are allowed to draw. */
private RectF mDrawingRect;
+ /** Side of the satValPanel square. */
+ private float satValSide;
+
private GradientPanel satValPanel;
private GradientPanel huePanel;
private GradientPanel alphaPanel;
+ private GradientPanel[] rgbPanel = new GradientPanel[3];
private Point mStartTouchPoint = null;
@@ -83,6 +91,7 @@ public class ColorPickerView extends View {
mDensity = getContext().getResources().getDisplayMetrics().density;
HUE_PANEL_WIDTH *= mDensity;
ALPHA_PANEL_HEIGHT *= mDensity;
+ RGB_PANEL_SIZE *= mDensity;
PANEL_SPACING *= mDensity;
mDrawingOffset = Math.max(5, BORDER_WIDTH_PX) * mDensity * 1.5f;
@@ -93,6 +102,11 @@ public class ColorPickerView extends View {
setFocusableInTouchMode(true);
}
+ /** Return true if the current orientation is landscape. */
+ private boolean landScapeView() {
+ return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
+ }
+
@Override
protected void onDraw(Canvas canvas) {
if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0)
@@ -104,6 +118,9 @@ public class ColorPickerView extends View {
huePanel.draw(canvas);
if (alphaPanel != null)
alphaPanel.draw(canvas);
+ for (int i = 0; i < 3; i++)
+ if (rgbPanel[i] != null)
+ rgbPanel[i].draw(canvas);
}
@Override
@@ -137,7 +154,8 @@ public class ColorPickerView extends View {
if (mStartTouchPoint == null)
return false;
- for (GradientPanel pnl : new GradientPanel[]{satValPanel, huePanel, alphaPanel}) {
+ for (GradientPanel pnl : new GradientPanel[]{satValPanel, huePanel, alphaPanel,
+ rgbPanel[0], rgbPanel[1], rgbPanel[2]}) {
if (pnl != null && pnl.contains(mStartTouchPoint)) {
Point curPnt = new Point((int)event.getX(),
(int)event.getY());
@@ -153,51 +171,56 @@ public class ColorPickerView extends View {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-
int widthAllowed = MeasureSpec.getSize(widthMeasureSpec);
int heightAllowed = MeasureSpec.getSize(heightMeasureSpec);
-
- widthAllowed = chooseWidth(widthMode, widthAllowed);
- heightAllowed = chooseHeight(heightMode, heightAllowed);
- int width = (int) (heightAllowed - ALPHA_PANEL_HEIGHT + HUE_PANEL_WIDTH);
- int height;
- if (width > widthAllowed) {
- width = widthAllowed;
- height = (int) (widthAllowed - HUE_PANEL_WIDTH + ALPHA_PANEL_HEIGHT);
- } else {
- height = heightAllowed;
- }
+ widthAllowed = chooseSize(widthMode, widthAllowed, getPreferredWidth());
+ heightAllowed = chooseSize(heightMode, heightAllowed, getPreferredHeight());
- setMeasuredDimension(width, height);
- }
+ float side = getSatValSide(widthAllowed, heightAllowed);
+ float width = side + getExtraWidth();
+ float height = side + getExtraHeight();
- private int chooseWidth(int mode, int size) {
- if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
- return size;
- } else { // (mode == MeasureSpec.UNSPECIFIED)
- return getPreferredWidth();
- }
- }
-
- private int chooseHeight(int mode, int size) {
- if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
- return size;
- } else { // (mode == MeasureSpec.UNSPECIFIED)
- return getPreferredHeight();
- }
+ int newWidth = widthMode == MeasureSpec.EXACTLY ? widthAllowed : (int)width;
+ int newHeight = heightMode == MeasureSpec.EXACTLY ? heightAllowed : (int)height;
+ setMeasuredDimension(newWidth, newHeight);
}
private int getPreferredWidth() {
- int width = getPreferredHeight();
- width -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
- return (int) (width + HUE_PANEL_WIDTH + PANEL_SPACING);
+ return (int)(200 * mDensity + getExtraWidth());
}
private int getPreferredHeight() {
- int height = (int)(200 * mDensity);
- height += PANEL_SPACING + ALPHA_PANEL_HEIGHT;
- return height;
+ return (int)(200 * mDensity + getExtraHeight());
+ }
+
+ private int chooseSize(int mode, int size, int preferred) {
+ if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY)
+ return size;
+ return preferred; // MeasureSpec.UNSPECIFIED
+ }
+
+ /** Compute side of satValPanel given total available width/height. */
+ private float getSatValSide(float width, float height) {
+ float side1 = width - getExtraWidth();
+ float side2 = height - getExtraHeight();
+ return Math.min(side1, side2);
+ }
+
+ /** Amount of space to the right of the satVal panel. */
+ private float getExtraWidth() {
+ float ret = PANEL_SPACING + HUE_PANEL_WIDTH;
+ if (landScapeView())
+ ret += 3 * (PANEL_SPACING + RGB_PANEL_SIZE);
+ return ret;
+ }
+
+ /** Amount of space below the satVal panel. */
+ private float getExtraHeight() {
+ float ret = PANEL_SPACING + ALPHA_PANEL_HEIGHT;
+ if (!landScapeView())
+ ret += 3 * (PANEL_SPACING + RGB_PANEL_SIZE);
+ return ret;
}
@Override
@@ -210,20 +233,23 @@ public class ColorPickerView extends View {
mDrawingRect.top = mDrawingOffset + getPaddingTop();
mDrawingRect.bottom = h - mDrawingOffset - getPaddingBottom();
+ satValSide = getSatValSide(mDrawingRect.width(),
+ mDrawingRect.height());
+
setUpSatValPanel();
setUpHuePanel();
setUpAlphaPanel();
+ setUpRGBPanels();
}
private void setUpSatValPanel() {
RectF dRect = mDrawingRect;
- float panelSide = dRect.height() - BORDER_WIDTH_PX * 2;
- panelSide -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
+ float b = BORDER_WIDTH_PX;
- float left = dRect.left + BORDER_WIDTH_PX;
- float right = left + panelSide;
- float top = dRect.top + BORDER_WIDTH_PX;
- float bottom = top + panelSide;
+ float left = dRect.left + b;
+ float right = left + satValSide - 2 * b;
+ float top = dRect.top + b;
+ float bottom = top + satValSide - 2 * b;
RectF satValRect = new RectF(left,top, right, bottom);
satValPanel = new SatValGradientPanel(satValRect, color, mDensity);
@@ -231,11 +257,12 @@ public class ColorPickerView extends View {
private void setUpHuePanel() {
RectF dRect = mDrawingRect;
+ float b = BORDER_WIDTH_PX;
- float left = dRect.right - HUE_PANEL_WIDTH + BORDER_WIDTH_PX;
- float right = dRect.right - BORDER_WIDTH_PX;
- float top = dRect.top + BORDER_WIDTH_PX;
- float bottom = dRect.bottom - BORDER_WIDTH_PX - (PANEL_SPACING + ALPHA_PANEL_HEIGHT);
+ float left = dRect.left + satValSide + PANEL_SPACING + b;
+ float right = left + HUE_PANEL_WIDTH - 2 * b;
+ float top = dRect.top + b;
+ float bottom = top + satValSide - 2 * b;
RectF hueRect = new RectF(left, top, right, bottom);
huePanel = new HueGradientPanel(hueRect, color, mDensity);
@@ -243,16 +270,45 @@ public class ColorPickerView extends View {
private void setUpAlphaPanel() {
RectF dRect = mDrawingRect;
+ float b = BORDER_WIDTH_PX;
- float left = dRect.left + BORDER_WIDTH_PX;
- float right = dRect.right - BORDER_WIDTH_PX;
- float top = dRect.bottom - ALPHA_PANEL_HEIGHT + BORDER_WIDTH_PX;
- float bottom = dRect.bottom - BORDER_WIDTH_PX;
+ float left = dRect.left + b;
+ float right = dRect.right - b;
+ float top = dRect.top + satValSide + PANEL_SPACING + b;
+ float bottom = top + ALPHA_PANEL_HEIGHT - 2 * b;
RectF alphaRect = new RectF(left, top, right, bottom);
alphaPanel = new AlphaGradientPanel(alphaRect, color, mDensity);
}
+ private void setUpRGBPanels() {
+ RectF dRect = mDrawingRect;
+ float b = BORDER_WIDTH_PX;
+ float w = RGB_PANEL_SIZE;
+ float s = PANEL_SPACING;
+ if (!landScapeView()) {
+ float offs = dRect.top + satValSide + s + ALPHA_PANEL_HEIGHT;
+ for (int i = 0; i < 3; i++) {
+ float left = dRect.left + b;
+ float right = dRect.right - b;
+ float top = offs + i * (s + w) + s + b;
+ float bottom = top + w - 2 * b;
+ RectF rgbRect = new RectF(left, top, right, bottom);
+ rgbPanel[i] = new RGBGradientPanel(i, rgbRect, color, mDensity, true);
+ }
+ } else {
+ float offs = dRect.left + satValSide + s + HUE_PANEL_WIDTH;
+ for (int i = 0; i < 3; i++) {
+ float left = offs + i * (s + w) + s + b;
+ float right = left + w - 2 * b;
+ float top = dRect.top + b;
+ float bottom = top + satValSide - 2 * b;
+ RectF rgbRect = new RectF(left, top, right, bottom);
+ rgbPanel[i] = new RGBGradientPanel(i, rgbRect, color, mDensity, false);
+ }
+ }
+ }
+
/**
* Set a OnColorChangedListener to get notified when the color
* selected by the user has changed.
diff --git a/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/RGBGradientPanel.java b/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/RGBGradientPanel.java
new file mode 100644
index 0000000..a1f16d1
--- /dev/null
+++ b/DroidFishApp/src/main/java/net/margaritov/preference/colorpicker/RGBGradientPanel.java
@@ -0,0 +1,80 @@
+package net.margaritov.preference.colorpicker;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Point;
+import android.graphics.RectF;
+import android.graphics.Shader;
+
+public class RGBGradientPanel extends GradientPanel {
+ private final int component; // 0=red, 1=green, 2=blue
+ private final int colorMask;
+ private final boolean horizontal;
+
+ /** Constructor. */
+ RGBGradientPanel(int component, RectF rect, AHSVColor color, float density,
+ boolean horizontal) {
+ super(rect, color, density, null);
+ this.component = component;
+ switch (component) {
+ case 0: colorMask = 0x00ff0000; break;
+ case 1: colorMask = 0x0000ff00; break;
+ case 2: colorMask = 0x000000ff; break;
+ default: colorMask = 0; break;
+ }
+ this.horizontal = horizontal;
+ }
+
+ @Override
+ protected void setGradientPaint() {
+ int rgb = color.getARGB();
+ int color00 = (rgb & ~colorMask) | 0xff000000;
+ int colorFF = (rgb | colorMask) | 0xff000000;
+ Shader rgbShader;
+ if (horizontal) {
+ rgbShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
+ color00, colorFF, Shader.TileMode.CLAMP);
+ } else {
+ rgbShader = new LinearGradient(rect.left, rect.bottom, rect.left, rect.top,
+ color00, colorFF, Shader.TileMode.CLAMP);
+ }
+ gradientPaint.setShader(rgbShader);
+ }
+
+ protected void drawTracker(Canvas canvas) {
+ int val = color.getRGBComponent(component);
+ Point p = rgbComponentToPoint(val);
+ drawRectangleTracker(canvas, p, horizontal);
+ }
+
+ @Override
+ void updateColor(Point point) {
+ int rgbVal = pointToRgbComponent(point);
+ color.setRGBComponent(component, rgbVal);
+ }
+
+ private Point rgbComponentToPoint(int val) {
+ if (horizontal) {
+ float width = rect.width();
+ return new Point((int)((val * width / 0xff) + rect.left),
+ (int)rect.top);
+ } else {
+ float height = rect.height();
+ return new Point((int)rect.left,
+ (int)(rect.bottom - (val * height / 0xff)));
+ }
+ }
+
+ private int pointToRgbComponent(Point p) {
+ if (horizontal) {
+ int width = (int)rect.width();
+ int x = Math.min(Math.max(p.x - (int)rect.left, 0), width);
+ return x * 0xff / width;
+ } else {
+ int height = (int)rect.height();
+ int y = Math.min(Math.max((int)rect.bottom - p.y, 0), height);
+ return y * 0xff / height;
+ }
+ }
+}
diff --git a/DroidFishApp/src/main/res/layout-land/dialog_color_picker.xml b/DroidFishApp/src/main/res/layout-land/dialog_color_picker.xml
index 8548229..50f18b6 100644
--- a/DroidFishApp/src/main/res/layout-land/dialog_color_picker.xml
+++ b/DroidFishApp/src/main/res/layout-land/dialog_color_picker.xml
@@ -30,8 +30,19 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
+ android:layout_weight="1.0"
android:layout_marginBottom="10dp">
+
+
+ android:layout_height="40dp" />
+ android:layout_height="40dp" />
diff --git a/DroidFishApp/src/main/res/layout/dialog_color_picker.xml b/DroidFishApp/src/main/res/layout/dialog_color_picker.xml
index bb63b6b..7944fac 100644
--- a/DroidFishApp/src/main/res/layout/dialog_color_picker.xml
+++ b/DroidFishApp/src/main/res/layout/dialog_color_picker.xml
@@ -24,9 +24,18 @@
android:id="@+id/color_picker_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
android:tag="portrait" />
+
+