highlightingStyles();
+ void saveHighlightingStyle(HighlightingStyle style);
}
diff --git a/src/org/geometerplus/fbreader/book/XMLSerializer.java b/src/org/geometerplus/fbreader/book/XMLSerializer.java
index f3e526227..ed88c9bcd 100644
--- a/src/org/geometerplus/fbreader/book/XMLSerializer.java
+++ b/src/org/geometerplus/fbreader/book/XMLSerializer.java
@@ -309,13 +309,12 @@ class XMLSerializer extends AbstractSerializer {
@Override
public String serialize(HighlightingStyle style) {
final StringBuilder buffer = new StringBuilder();
- appendTag(buffer, "style", false,
- "id", String.valueOf(style.Id)
+ final ZLColor bgColor = style.getBackgroundColor();
+ appendTag(buffer, "style", true,
+ "id", String.valueOf(style.Id),
+ "name", style.getName(),
+ "bg-color", bgColor != null ? String.valueOf(bgColor.intValue()) : "-1"
);
- appendTag(buffer, "bg-color", true,
- "value", String.valueOf(style.BackgroundColor.getIntValue())
- );
- closeTag(buffer, "style");
return buffer.toString();
}
@@ -961,9 +960,6 @@ class XMLSerializer extends AbstractSerializer {
private static final class StyleDeserializer extends DefaultHandler {
private HighlightingStyle myStyle;
- private int myId = -1;
- private int myColor;
-
public HighlightingStyle getStyle() {
return myStyle;
}
@@ -971,29 +967,22 @@ class XMLSerializer extends AbstractSerializer {
@Override
public void startDocument() {
myStyle = null;
- myId = -1;
- }
-
- @Override
- public void endDocument() {
- if (myId != -1) {
- myStyle = new HighlightingStyle(myId, new ZLColor(myColor));
- }
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("style".equals(localName)) {
try {
- myId = Integer.parseInt(attributes.getValue("id"));
+ final int id = Integer.parseInt(attributes.getValue("id"));
+ if (id != -1) {
+ final int rgb = Integer.parseInt(attributes.getValue("bg-color"));
+ final ZLColor color = rgb != -1 ? new ZLColor(rgb) : null;
+ myStyle = new HighlightingStyle(
+ id, attributes.getValue("name"), color
+ );
+ }
} catch (Exception e) {
- throw new SAXException("XML parsing error", e);
- }
- } else if ("bg-color".equals(localName)) {
- try {
- myColor = Integer.parseInt(attributes.getValue("value"));
- } catch (Exception e) {
- throw new SAXException("XML parsing error", e);
+ // ignore
}
}
}
diff --git a/src/org/geometerplus/fbreader/fbreader/BookmarkHighlighting.java b/src/org/geometerplus/fbreader/fbreader/BookmarkHighlighting.java
index c7da0541d..566b5b890 100644
--- a/src/org/geometerplus/fbreader/fbreader/BookmarkHighlighting.java
+++ b/src/org/geometerplus/fbreader/fbreader/BookmarkHighlighting.java
@@ -51,6 +51,6 @@ public final class BookmarkHighlighting extends ZLTextSimpleHighlighting {
@Override
public ZLColor getBackgroundColor() {
final HighlightingStyle bmStyle = Collection.getHighlightingStyle(Bookmark.getStyleId());
- return bmStyle != null ? bmStyle.BackgroundColor : new ZLColor(255, 255, 255);
+ return bmStyle != null ? bmStyle.getBackgroundColor() : null;
}
}
diff --git a/src/org/geometerplus/fbreader/fbreader/FBReaderApp.java b/src/org/geometerplus/fbreader/fbreader/FBReaderApp.java
index 8e70fbb06..dffa78b92 100644
--- a/src/org/geometerplus/fbreader/fbreader/FBReaderApp.java
+++ b/src/org/geometerplus/fbreader/fbreader/FBReaderApp.java
@@ -118,8 +118,9 @@ public final class FBReaderApp extends ZLApplication {
collection.addListener(new IBookCollection.Listener() {
public void onBookEvent(BookEvent event, Book book) {
switch (event) {
+ case BookmarkStyleChanged:
case BookmarksUpdated:
- if (Model != null && book.equals(Model.Book)) {
+ if (Model != null && (book == null || book.equals(Model.Book))) {
if (BookTextView.getModel() != null) {
setBookmarkHighlightings(BookTextView, null);
}
diff --git a/src/org/geometerplus/zlibrary/core/options/ZLColorOption.java b/src/org/geometerplus/zlibrary/core/options/ZLColorOption.java
index 68673e9a7..ceaf258d6 100644
--- a/src/org/geometerplus/zlibrary/core/options/ZLColorOption.java
+++ b/src/org/geometerplus/zlibrary/core/options/ZLColorOption.java
@@ -37,7 +37,7 @@ public final class ZLColorOption extends ZLOption {
if (value != null) {
try {
int intValue = Integer.parseInt(value);
- if (myValue.getIntValue() != intValue) {
+ if (myValue.intValue() != intValue) {
myValue = new ZLColor(intValue);
}
} catch (NumberFormatException e) {
@@ -61,7 +61,7 @@ public final class ZLColorOption extends ZLOption {
if (colorValue.equals(myDefaultValue)) {
unsetConfigValue();
} else {
- setConfigValue("" + colorValue.getIntValue());
+ setConfigValue(String.valueOf(colorValue.intValue()));
}
}
}
diff --git a/src/org/geometerplus/zlibrary/core/util/ZLColor.java b/src/org/geometerplus/zlibrary/core/util/ZLColor.java
index 7d0b59355..324cb5487 100644
--- a/src/org/geometerplus/zlibrary/core/util/ZLColor.java
+++ b/src/org/geometerplus/zlibrary/core/util/ZLColor.java
@@ -40,7 +40,7 @@ public final class ZLColor {
Blue = (short)(intValue & 0xFF);
}
- public int getIntValue() {
+ public int intValue() {
return (Red << 16) + (Green << 8) + Blue;
}
@@ -60,7 +60,7 @@ public final class ZLColor {
@Override
public int hashCode() {
- return getIntValue();
+ return intValue();
}
@Override
diff --git a/src/org/geometerplus/zlibrary/text/view/ZLTextView.java b/src/org/geometerplus/zlibrary/text/view/ZLTextView.java
index 8acb412cf..23a4dc293 100644
--- a/src/org/geometerplus/zlibrary/text/view/ZLTextView.java
+++ b/src/org/geometerplus/zlibrary/text/view/ZLTextView.java
@@ -837,6 +837,10 @@ public abstract class ZLTextView extends ZLTextViewBase {
final ZLTextElementArea fromArea = page.TextElementMap.get(from);
final ZLTextElementArea toArea = page.TextElementMap.get(to - 1);
for (ZLTextHighlighting h : hilites) {
+ final ZLColor bgColor = h.getBackgroundColor();
+ if (bgColor == null) {
+ continue;
+ }
final ZLTextElementArea selectionStartArea = h.getStartArea(page);
if (selectionStartArea == null || selectionStartArea.compareTo(toArea) > 0) {
continue;
@@ -859,7 +863,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
} else {
right = selectionEndArea.XEnd;
}
- getContext().setFillColor(h.getBackgroundColor());
+ getContext().setFillColor(bgColor);
getContext().fillRectangle(left, top, right, bottom);
}
}
@@ -1587,7 +1591,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
}
synchronized (myHighlightings) {
for (ZLTextHighlighting h : myHighlightings) {
- if (h.intersects(region)) {
+ if (h.getBackgroundColor() != null && h.intersects(region)) {
return h;
}
}
diff --git a/third-party/AmbilWarna/AmbilWarna.iml b/third-party/AmbilWarna/AmbilWarna.iml
new file mode 100644
index 000000000..a74440d60
--- /dev/null
+++ b/third-party/AmbilWarna/AmbilWarna.iml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/third-party/AmbilWarna/AndroidManifest.xml b/third-party/AmbilWarna/AndroidManifest.xml
new file mode 100644
index 000000000..20917f639
--- /dev/null
+++ b/third-party/AmbilWarna/AndroidManifest.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/third-party/AmbilWarna/build.xml b/third-party/AmbilWarna/build.xml
new file mode 100644
index 000000000..86c2b053f
--- /dev/null
+++ b/third-party/AmbilWarna/build.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/third-party/AmbilWarna/project.properties b/third-party/AmbilWarna/project.properties
new file mode 100644
index 000000000..ce256fda4
--- /dev/null
+++ b/third-party/AmbilWarna/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+android.library=true
+# Indicates whether an apk should be generated for each density.
+split.density=false
+# Project target.
+target=android-11
diff --git a/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_arrow_down.png b/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_arrow_down.png
new file mode 100644
index 000000000..d2aa1b09f
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_arrow_down.png differ
diff --git a/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_arrow_right.png b/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_arrow_right.png
new file mode 100644
index 000000000..faf1bd757
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_arrow_right.png differ
diff --git a/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_cursor.png b/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_cursor.png
new file mode 100644
index 000000000..28cebc326
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_cursor.png differ
diff --git a/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_target.png b/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_target.png
new file mode 100644
index 000000000..6f7bf906f
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-hdpi/ambilwarna_target.png differ
diff --git a/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_arrow_down.png b/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_arrow_down.png
new file mode 100644
index 000000000..19d6d4ef2
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_arrow_down.png differ
diff --git a/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_arrow_right.png b/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_arrow_right.png
new file mode 100644
index 000000000..ace7986bf
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_arrow_right.png differ
diff --git a/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_cursor.png b/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_cursor.png
new file mode 100644
index 000000000..539eeeb96
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_cursor.png differ
diff --git a/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_target.png b/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_target.png
new file mode 100644
index 000000000..4fdf59778
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-ldpi/ambilwarna_target.png differ
diff --git a/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_arrow_down.png b/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_arrow_down.png
new file mode 100644
index 000000000..592dd7ca6
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_arrow_down.png differ
diff --git a/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_arrow_right.png b/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_arrow_right.png
new file mode 100644
index 000000000..04f655adc
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_arrow_right.png differ
diff --git a/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_cursor.png b/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_cursor.png
new file mode 100644
index 000000000..ddea31674
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_cursor.png differ
diff --git a/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_target.png b/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_target.png
new file mode 100644
index 000000000..bb4b1eb72
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable-xhdpi/ambilwarna_target.png differ
diff --git a/third-party/AmbilWarna/res/drawable/ambilwarna_arrow_down.png b/third-party/AmbilWarna/res/drawable/ambilwarna_arrow_down.png
new file mode 100644
index 000000000..5f4345523
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable/ambilwarna_arrow_down.png differ
diff --git a/third-party/AmbilWarna/res/drawable/ambilwarna_arrow_right.png b/third-party/AmbilWarna/res/drawable/ambilwarna_arrow_right.png
new file mode 100644
index 000000000..23d546192
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable/ambilwarna_arrow_right.png differ
diff --git a/third-party/AmbilWarna/res/drawable/ambilwarna_cursor.png b/third-party/AmbilWarna/res/drawable/ambilwarna_cursor.png
new file mode 100644
index 000000000..c336e883c
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable/ambilwarna_cursor.png differ
diff --git a/third-party/AmbilWarna/res/drawable/ambilwarna_hue.png b/third-party/AmbilWarna/res/drawable/ambilwarna_hue.png
new file mode 100644
index 000000000..09d28397f
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable/ambilwarna_hue.png differ
diff --git a/third-party/AmbilWarna/res/drawable/ambilwarna_target.png b/third-party/AmbilWarna/res/drawable/ambilwarna_target.png
new file mode 100644
index 000000000..56fa0de9c
Binary files /dev/null and b/third-party/AmbilWarna/res/drawable/ambilwarna_target.png differ
diff --git a/third-party/AmbilWarna/res/layout-land/ambilwarna_dialog.xml b/third-party/AmbilWarna/res/layout-land/ambilwarna_dialog.xml
new file mode 100644
index 000000000..236e10eef
--- /dev/null
+++ b/third-party/AmbilWarna/res/layout-land/ambilwarna_dialog.xml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/third-party/AmbilWarna/res/layout/ambilwarna_dialog.xml b/third-party/AmbilWarna/res/layout/ambilwarna_dialog.xml
new file mode 100644
index 000000000..5cb275593
--- /dev/null
+++ b/third-party/AmbilWarna/res/layout/ambilwarna_dialog.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/third-party/AmbilWarna/res/layout/ambilwarna_pref_widget.xml b/third-party/AmbilWarna/res/layout/ambilwarna_pref_widget.xml
new file mode 100644
index 000000000..667b15e49
--- /dev/null
+++ b/third-party/AmbilWarna/res/layout/ambilwarna_pref_widget.xml
@@ -0,0 +1,10 @@
+
+
diff --git a/third-party/AmbilWarna/res/values-land/dimen.xml b/third-party/AmbilWarna/res/values-land/dimen.xml
new file mode 100644
index 000000000..f1c483268
--- /dev/null
+++ b/third-party/AmbilWarna/res/values-land/dimen.xml
@@ -0,0 +1,5 @@
+
+
+ 240dp
+ 120dp
+
\ No newline at end of file
diff --git a/third-party/AmbilWarna/res/values-xlarge-land/dimen.xml b/third-party/AmbilWarna/res/values-xlarge-land/dimen.xml
new file mode 100644
index 000000000..1e72cca59
--- /dev/null
+++ b/third-party/AmbilWarna/res/values-xlarge-land/dimen.xml
@@ -0,0 +1,5 @@
+
+
+ 240dp
+ 240dp
+
\ No newline at end of file
diff --git a/third-party/AmbilWarna/res/values/dimen.xml b/third-party/AmbilWarna/res/values/dimen.xml
new file mode 100644
index 000000000..92f53a2ea
--- /dev/null
+++ b/third-party/AmbilWarna/res/values/dimen.xml
@@ -0,0 +1,7 @@
+
+
+ 240dp
+ 240dp
+ 30dp
+ 8dp
+
diff --git a/third-party/AmbilWarna/src/yuku/ambilwarna/AmbilWarnaDialog.java b/third-party/AmbilWarna/src/yuku/ambilwarna/AmbilWarnaDialog.java
new file mode 100644
index 000000000..968aff4cc
--- /dev/null
+++ b/third-party/AmbilWarna/src/yuku/ambilwarna/AmbilWarnaDialog.java
@@ -0,0 +1,198 @@
+package yuku.ambilwarna;
+
+import android.app.*;
+import android.content.*;
+import android.content.DialogInterface.OnCancelListener;
+import android.graphics.*;
+import android.view.*;
+import android.widget.*;
+
+public class AmbilWarnaDialog {
+ public interface OnAmbilWarnaListener {
+ void onCancel(AmbilWarnaDialog dialog);
+ void onOk(AmbilWarnaDialog dialog, int color);
+ }
+
+ final AlertDialog dialog;
+ final OnAmbilWarnaListener listener;
+ final View viewHue;
+ final AmbilWarnaKotak viewSatVal;
+ final ImageView viewCursor;
+ final View viewOldColor;
+ final View viewNewColor;
+ final ImageView viewTarget;
+ final ViewGroup viewContainer;
+ final float[] currentColorHsv = new float[3];
+
+ /**
+ * create an AmbilWarnaDialog. call this only from OnCreateDialog() or from a background thread.
+ *
+ * @param context
+ * current context
+ * @param color
+ * current color
+ * @param listener
+ * an OnAmbilWarnaListener, allowing you to get back error or
+ */
+ public AmbilWarnaDialog(final Context context, int color, OnAmbilWarnaListener listener) {
+ this.listener = listener;
+ Color.colorToHSV(color, currentColorHsv);
+
+ final View view = LayoutInflater.from(context).inflate(R.layout.ambilwarna_dialog, null);
+ viewHue = view.findViewById(R.id.ambilwarna_viewHue);
+ viewSatVal = (AmbilWarnaKotak) view.findViewById(R.id.ambilwarna_viewSatBri);
+ viewCursor = (ImageView) view.findViewById(R.id.ambilwarna_cursor);
+ viewOldColor = view.findViewById(R.id.ambilwarna_warnaLama);
+ viewNewColor = view.findViewById(R.id.ambilwarna_warnaBaru);
+ viewTarget = (ImageView) view.findViewById(R.id.ambilwarna_target);
+ viewContainer = (ViewGroup) view.findViewById(R.id.ambilwarna_viewContainer);
+
+ viewSatVal.setHue(getHue());
+ viewOldColor.setBackgroundColor(color);
+ viewNewColor.setBackgroundColor(color);
+
+ viewHue.setOnTouchListener(new View.OnTouchListener() {
+ @Override public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_MOVE
+ || event.getAction() == MotionEvent.ACTION_DOWN
+ || event.getAction() == MotionEvent.ACTION_UP) {
+
+ float y = event.getY();
+ if (y < 0.f) y = 0.f;
+ if (y > viewHue.getMeasuredHeight()) y = viewHue.getMeasuredHeight() - 0.001f; // to avoid looping from end to start.
+ float hue = 360.f - 360.f / viewHue.getMeasuredHeight() * y;
+ if (hue == 360.f) hue = 0.f;
+ setHue(hue);
+
+ // update view
+ viewSatVal.setHue(getHue());
+ moveCursor();
+ viewNewColor.setBackgroundColor(getColor());
+
+ return true;
+ }
+ return false;
+ }
+ });
+ viewSatVal.setOnTouchListener(new View.OnTouchListener() {
+ @Override public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_MOVE
+ || event.getAction() == MotionEvent.ACTION_DOWN
+ || event.getAction() == MotionEvent.ACTION_UP) {
+
+ float x = event.getX(); // touch event are in dp units.
+ float y = event.getY();
+
+ if (x < 0.f) x = 0.f;
+ if (x > viewSatVal.getMeasuredWidth()) x = viewSatVal.getMeasuredWidth();
+ if (y < 0.f) y = 0.f;
+ if (y > viewSatVal.getMeasuredHeight()) y = viewSatVal.getMeasuredHeight();
+
+ setSat(1.f / viewSatVal.getMeasuredWidth() * x);
+ setVal(1.f - (1.f / viewSatVal.getMeasuredHeight() * y));
+
+ // update view
+ moveTarget();
+ viewNewColor.setBackgroundColor(getColor());
+
+ return true;
+ }
+ return false;
+ }
+ });
+
+ dialog = new AlertDialog.Builder(context)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override public void onClick(DialogInterface dialog, int which) {
+ if (AmbilWarnaDialog.this.listener != null) {
+ AmbilWarnaDialog.this.listener.onOk(AmbilWarnaDialog.this, getColor());
+ }
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override public void onClick(DialogInterface dialog, int which) {
+ if (AmbilWarnaDialog.this.listener != null) {
+ AmbilWarnaDialog.this.listener.onCancel(AmbilWarnaDialog.this);
+ }
+ }
+ })
+ .setOnCancelListener(new OnCancelListener() {
+ // if back button is used, call back our listener.
+ @Override public void onCancel(DialogInterface paramDialogInterface) {
+ if (AmbilWarnaDialog.this.listener != null) {
+ AmbilWarnaDialog.this.listener.onCancel(AmbilWarnaDialog.this);
+ }
+
+ }
+ })
+ .create();
+ // kill all padding from the dialog window
+ dialog.setView(view, 0, 0, 0, 0);
+
+ // move cursor & target on first draw
+ ViewTreeObserver vto = view.getViewTreeObserver();
+ vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override public void onGlobalLayout() {
+ moveCursor();
+ moveTarget();
+ view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
+ }
+ });
+ }
+
+ protected void moveCursor() {
+ float y = viewHue.getMeasuredHeight() - (getHue() * viewHue.getMeasuredHeight() / 360.f);
+ if (y == viewHue.getMeasuredHeight()) y = 0.f;
+ RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) viewCursor.getLayoutParams();
+ layoutParams.leftMargin = (int) (viewHue.getLeft() - Math.floor(viewCursor.getMeasuredWidth() / 2) - viewContainer.getPaddingLeft());
+ ;
+ layoutParams.topMargin = (int) (viewHue.getTop() + y - Math.floor(viewCursor.getMeasuredHeight() / 2) - viewContainer.getPaddingTop());
+ ;
+ viewCursor.setLayoutParams(layoutParams);
+ }
+
+ protected void moveTarget() {
+ float x = getSat() * viewSatVal.getMeasuredWidth();
+ float y = (1.f - getVal()) * viewSatVal.getMeasuredHeight();
+ RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) viewTarget.getLayoutParams();
+ layoutParams.leftMargin = (int) (viewSatVal.getLeft() + x - Math.floor(viewTarget.getMeasuredWidth() / 2) - viewContainer.getPaddingLeft());
+ layoutParams.topMargin = (int) (viewSatVal.getTop() + y - Math.floor(viewTarget.getMeasuredHeight() / 2) - viewContainer.getPaddingTop());
+ viewTarget.setLayoutParams(layoutParams);
+ }
+
+ private int getColor() {
+ return Color.HSVToColor(currentColorHsv);
+ }
+
+ private float getHue() {
+ return currentColorHsv[0];
+ }
+
+ private float getSat() {
+ return currentColorHsv[1];
+ }
+
+ private float getVal() {
+ return currentColorHsv[2];
+ }
+
+ private void setHue(float hue) {
+ currentColorHsv[0] = hue;
+ }
+
+ private void setSat(float sat) {
+ currentColorHsv[1] = sat;
+ }
+
+ private void setVal(float val) {
+ currentColorHsv[2] = val;
+ }
+
+ public void show() {
+ dialog.show();
+ }
+
+ public AlertDialog getDialog() {
+ return dialog;
+ }
+}
diff --git a/third-party/AmbilWarna/src/yuku/ambilwarna/AmbilWarnaKotak.java b/third-party/AmbilWarna/src/yuku/ambilwarna/AmbilWarnaKotak.java
new file mode 100644
index 000000000..37959376d
--- /dev/null
+++ b/third-party/AmbilWarna/src/yuku/ambilwarna/AmbilWarnaKotak.java
@@ -0,0 +1,46 @@
+package yuku.ambilwarna;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ComposeShader;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.Shader;
+import android.graphics.Shader.TileMode;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class AmbilWarnaKotak extends View {
+ Paint paint;
+ Shader luar;
+ final float[] color = { 1.f, 1.f, 1.f };
+
+ public AmbilWarnaKotak(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AmbilWarnaKotak(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (paint == null) {
+ paint = new Paint();
+ luar = new LinearGradient(0.f, 0.f, 0.f, this.getMeasuredHeight(), 0xffffffff, 0xff000000, TileMode.CLAMP);
+ }
+ int rgb = Color.HSVToColor(color);
+ Shader dalam = new LinearGradient(0.f, 0.f, this.getMeasuredWidth(), 0.f, 0xffffffff, rgb, TileMode.CLAMP);
+ ComposeShader shader = new ComposeShader(luar, dalam, PorterDuff.Mode.MULTIPLY);
+ paint.setShader(shader);
+ canvas.drawRect(0.f, 0.f, this.getMeasuredWidth(), this.getMeasuredHeight(), paint);
+ }
+
+ void setHue(float hue) {
+ color[0] = hue;
+ invalidate();
+ }
+}
diff --git a/third-party/AmbilWarna/src/yuku/ambilwarna/widget/AmbilWarnaPrefWidgetView.java b/third-party/AmbilWarna/src/yuku/ambilwarna/widget/AmbilWarnaPrefWidgetView.java
new file mode 100644
index 000000000..2d315c8ee
--- /dev/null
+++ b/third-party/AmbilWarna/src/yuku/ambilwarna/widget/AmbilWarnaPrefWidgetView.java
@@ -0,0 +1,45 @@
+package yuku.ambilwarna.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.util.AttributeSet;
+import android.util.FloatMath;
+import android.view.View;
+
+public class AmbilWarnaPrefWidgetView extends View {
+ Paint paint;
+ float rectSize;
+ float strokeWidth;
+
+ boolean drawCross;
+
+ public AmbilWarnaPrefWidgetView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ float density = context.getResources().getDisplayMetrics().density;
+ rectSize = FloatMath.floor(24.f * density + 0.5f);
+ strokeWidth = FloatMath.floor(1.f * density + 0.5f);
+
+ paint = new Paint();
+ paint.setColor(0xffffffff);
+ paint.setStyle(Style.STROKE);
+ paint.setStrokeWidth(strokeWidth);
+ }
+
+ public void showCross(boolean show) {
+ drawCross = show;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.drawRect(strokeWidth, strokeWidth, rectSize - strokeWidth, rectSize - strokeWidth, paint);
+ if (drawCross) {
+ canvas.drawLine(strokeWidth, strokeWidth, rectSize - strokeWidth, rectSize - strokeWidth, paint);
+ canvas.drawLine(strokeWidth, rectSize - strokeWidth, rectSize - strokeWidth, strokeWidth, paint);
+ }
+ }
+}
diff --git a/third-party/AmbilWarna/src/yuku/ambilwarna/widget/AmbilWarnaPreference.java b/third-party/AmbilWarna/src/yuku/ambilwarna/widget/AmbilWarnaPreference.java
new file mode 100644
index 000000000..d9daecdbf
--- /dev/null
+++ b/third-party/AmbilWarna/src/yuku/ambilwarna/widget/AmbilWarnaPreference.java
@@ -0,0 +1,129 @@
+package yuku.ambilwarna.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+
+import yuku.ambilwarna.AmbilWarnaDialog;
+import yuku.ambilwarna.R;
+
+public class AmbilWarnaPreference extends Preference {
+ int value;
+
+ public AmbilWarnaPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setWidgetLayoutResource(R.layout.ambilwarna_pref_widget);
+ }
+
+ @Override protected void onBindView(View view) {
+ super.onBindView(view);
+
+ // Set our custom views inside the layout
+ final View kotak = view.findViewById(R.id.ambilwarna_pref_widget_kotak);
+ if (kotak != null) {
+ kotak.setBackgroundColor(value);
+ }
+ }
+
+ @Override protected void onClick() {
+ new AmbilWarnaDialog(getContext(), value, new AmbilWarnaDialog.OnAmbilWarnaListener() {
+ @Override public void onOk(AmbilWarnaDialog dialog, int color) {
+ if (!callChangeListener(color)) return; // They don't want the value to be set
+ value = color;
+ persistInt(value);
+ notifyChanged();
+ }
+
+ @Override public void onCancel(AmbilWarnaDialog dialog) {
+ // nothing to do
+ }
+ }).show();
+ }
+
+ public void forceSetValue(int value) {
+ this.value = value;
+ persistInt(value);
+ notifyChanged();
+ }
+
+ @Override protected Object onGetDefaultValue(TypedArray a, int index) {
+ // This preference type's value type is Integer, so we read the default value from the attributes as an Integer.
+ return a.getInteger(index, 0);
+ }
+
+ @Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ if (restoreValue) { // Restore state
+ value = getPersistedInt(value);
+ } else { // Set state
+ int value = (Integer) defaultValue;
+ this.value = value;
+ persistInt(value);
+ }
+ }
+
+ /*
+ * Suppose a client uses this preference type without persisting. We
+ * must save the instance state so it is able to, for example, survive
+ * orientation changes.
+ */
+ @Override protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ if (isPersistent()) return superState; // No need to save instance state since it's persistent
+
+ final SavedState myState = new SavedState(superState);
+ myState.value = value;
+ return myState;
+ }
+
+ @Override protected void onRestoreInstanceState(Parcelable state) {
+ if (!state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ // Restore the instance state
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ this.value = myState.value;
+ notifyChanged();
+ }
+
+ /**
+ * SavedState, a subclass of {@link BaseSavedState}, will store the state
+ * of MyPreference, a subclass of Preference.
+ *
+ * It is important to always call through to super methods.
+ */
+ private static class SavedState extends BaseSavedState {
+ int value;
+
+ public SavedState(Parcel source) {
+ super(source);
+ value = source.readInt();
+ }
+
+ @Override public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(value);
+ }
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ @SuppressWarnings("unused") public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+}