aboutsummaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorJorge Ruesga <jorge@ruesga.com>2013-03-25 04:56:38 +0100
committerJorge Ruesga <jorge@ruesga.com>2013-03-27 00:16:04 +0100
commit8573124b80d19a9562a6e623022171b41dc4d183 (patch)
tree40aa0eca71ca3bd4e09abee5efa046f31cc2f308 /libs
parentd063637d6110ab2a762268d7ef20afeaa6f482af (diff)
downloadandroid_packages_apps_CMFileManager-8573124b80d19a9562a6e623022171b41dc4d183.tar.gz
android_packages_apps_CMFileManager-8573124b80d19a9562a6e623022171b41dc4d183.tar.bz2
android_packages_apps_CMFileManager-8573124b80d19a9562a6e623022171b41dc4d183.zip
CMFM: Editor initial highlight support + props syntax processor + others features
- This change enables support of syntax highlight in editor. Adds also the next syntax processors: * PropertiesSyntaxHighlightProcessor - Option for toggle "no suggestion" in editor - CleanUp Patchset 2: Theme color scheme support Patchset 3: Hexdump binary editor preference No suggestions editor preference Syntax Highlight color scheme Add android-syntax-highlight (CMFM) and color-picker-view libraries ColorPickerDialog and ColorPickerPreference Separate preference to its own file Extract themes strings from dark_theme.xml to strings.xml Rebased Change-Id: I9df65e6193d46ebafadee5d545dcde1fc5ce20e9 Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
Diffstat (limited to 'libs')
-rw-r--r--libs/android-syntax-highlight/CHANGELOG.md7
-rw-r--r--libs/android-syntax-highlight/LICENSE.md202
-rw-r--r--libs/android-syntax-highlight/README.md14
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java121
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java55
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java71
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java96
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java112
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java76
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java42
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java281
-rw-r--r--libs/color-picker-view/CHANGELOG.md4
-rw-r--r--libs/color-picker-view/LICENSE.md202
-rw-r--r--libs/color-picker-view/README.md18
-rw-r--r--libs/color-picker-view/src/afzkl/development/mColorPicker/drawables/AlphaPatternDrawable.java129
-rw-r--r--libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorDialogView.java463
-rw-r--r--libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPanelView.java174
-rw-r--r--libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPickerView.java998
18 files changed, 3065 insertions, 0 deletions
diff --git a/libs/android-syntax-highlight/CHANGELOG.md b/libs/android-syntax-highlight/CHANGELOG.md
new file mode 100644
index 00000000..84bfdb46
--- /dev/null
+++ b/libs/android-syntax-highlight/CHANGELOG.md
@@ -0,0 +1,7 @@
+ChangeLog
+========================
+
+Version 0.0.1
+-------------
+* Initial support
+* properties syntax highlight processor \ No newline at end of file
diff --git a/libs/android-syntax-highlight/LICENSE.md b/libs/android-syntax-highlight/LICENSE.md
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/libs/android-syntax-highlight/LICENSE.md
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ 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.
diff --git a/libs/android-syntax-highlight/README.md b/libs/android-syntax-highlight/README.md
new file mode 100644
index 00000000..3f7dc373
--- /dev/null
+++ b/libs/android-syntax-highlight/README.md
@@ -0,0 +1,14 @@
+Android Syntax Highlight Library
+================================
+
+A library for add syntax highlight to TextView and EditText widgets.
+
+This library was developed as part of the CMFileManager app.
+
+This source was released under the terms of
+[Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) license.
+
+Visit [CyanogenMod Github](https://github.com/CyanogenMod) and [CyanogenMod
+Code Review](http://review.cyanogenmod.com/) to get the source and patches.
+
+Copyright © 2013 The CyanogenMod Project
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java
new file mode 100644
index 00000000..5e31dab7
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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.cyanogenmod.filemanager.ash;
+
+import android.graphics.Color;
+
+/**
+ * An enumeration of all the color resources available for syntax highlight processors.
+ */
+public enum HighlightColors {
+
+ /**
+ * Text color
+ */
+ TEXT(
+ "ash_text", //$NON-NLS-1$
+ "ash_text_color", //$NON-NLS-1$
+ Color.argb(153, 0, 0, 0)),
+ /**
+ * Assignment text color
+ */
+ ASSIGNMENT(
+ "ash_assignment", //$NON-NLS-1$
+ "ash_assignment_color", //$NON-NLS-1$
+ Color.argb(153, 0, 0, 0)),
+ /**
+ * Single line comment color
+ */
+ SINGLE_LINE_COMMENT(
+ "ash_singleline_comment", //$NON-NLS-1$
+ "ash_singleline_comment_color", //$NON-NLS-1$
+ Color.argb(255, 63, 127, 95)),
+ /**
+ * Multiline line comment color
+ */
+ MULTILINE_LINE_COMMENT(
+ "ash_multiline_comment", //$NON-NLS-1$
+ "ash_multiline_comment_color", //$NON-NLS-1$
+ Color.argb(255, 127, 159, 191)),
+ /**
+ * Keyword color
+ */
+ KEYWORD(
+ "ash_keyword", //$NON-NLS-1$
+ "ash_keyword_color", //$NON-NLS-1$
+ Color.argb(255, 127, 0, 85)),
+ /**
+ * Quoted string color
+ */
+ QUOTED_STRING(
+ "ash_quoted_string", //$NON-NLS-1$
+ "ash_quoted_string_color", //$NON-NLS-1$
+ Color.argb(255, 42, 0, 255)),
+ /**
+ * Variable color
+ */
+ VARIABLE(
+ "ash_variable", //$NON-NLS-1$
+ "ash_variable_color", //$NON-NLS-1$
+ Color.argb(153, 0, 0, 192));
+
+
+ private final String mId;
+ private final String mResId;
+ private final int mDefault;
+
+ /**
+ * Constructor of <code>HighlightColors</code>
+ *
+ * @param id The id of the object
+ * @param resid The resource id
+ * @param def The default value
+ */
+ HighlightColors(String id, String resid, int def) {
+ this.mId = id;
+ this.mResId = resid;
+ this.mDefault = def;
+ }
+
+ /**
+ * Returns the identifier
+ *
+ * @return String The identifier
+ */
+ public String getId() {
+ return this.mId;
+ }
+
+ /**
+ * Returns the resource identifier
+ *
+ * @return String The resource identifier
+ */
+ public String getResId() {
+ return this.mResId;
+ }
+
+ /**
+ * Returns the default value
+ *
+ * @return String The default value
+ */
+ public int getDefault() {
+ return this.mDefault;
+ }
+
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java
new file mode 100644
index 00000000..11170e7c
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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.cyanogenmod.filemanager.ash;
+
+/**
+ * An interface that should be implemented by the library caller, to
+ * resolve resources needed by the syntax processors.
+ *
+ * @see HighlightColors
+ */
+public interface ISyntaxHighlightResourcesResolver {
+
+ /**
+ * Method that returns a string
+ *
+ * @param id The color unique id
+ * @param resid The resource identifier
+ * @return CharSequence The string
+ */
+ CharSequence getString(String id, String resid);
+
+ /**
+ * Method that returns an integer
+ *
+ * @param id The color unique id
+ * @param resid The resource identifier
+ * @param def The default value
+ * @return int The integer value
+ */
+ int getInteger(String id, String resid, int def);
+
+ /**
+ * Method that returns a color
+ *
+ * @param id The color unique id
+ * @param resid The resource identifier
+ * @param def The default value
+ * @return int The color
+ */
+ int getColor(String id, String resid, int def);
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java
new file mode 100644
index 00000000..283eba90
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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.cyanogenmod.filemanager.ash;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * A helper class for deal with patters
+ */
+public final class RegExpUtil {
+
+ /**
+ * A constant that is returned when the no expression matches.
+ */
+ public static final int NO_MATCH = -1;
+
+ /**
+ * New line pattern
+ */
+ public static final Pattern NEWLINE_PATTERN = Pattern.compile("(\r\n|\n|\r)"); //$NON-NLS-1$
+
+ /**
+ * Method that returns the last match position of a regexp,
+ *
+ * @param pattern The patter
+ * @param input The input
+ * @param withPattern Whether the return position should contains the pattern or not.
+ * @return int The matched position or -1
+ */
+ public static int getLastMatch(Pattern pattern, CharSequence input, boolean withPattern) {
+ Matcher m = pattern.matcher(input);
+ int p = NO_MATCH;
+ while (m.find()) {
+ p = withPattern ? m.start() : m.end();
+ }
+ return p;
+ }
+
+ /**
+ * Method that returns the next match position of a regexp,
+ *
+ * @param pattern The patter
+ * @param input The input
+ * @param withPattern Whether the return position should contains the pattern or not.
+ * @return int The matched position or -1
+ */
+ public static int getNextMatch(Pattern pattern, CharSequence input, boolean withPattern) {
+ Matcher m = pattern.matcher(input);
+ int p = NO_MATCH;
+ if (m.find()) {
+ return withPattern ? m.end() : m.start();
+ }
+ return p;
+ }
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java
new file mode 100644
index 00000000..20c85dc2
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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.cyanogenmod.filemanager.ash;
+
+import com.cyanogenmod.filemanager.ash.spi.PropertiesSyntaxHighlightProcessor;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A factory of <code>SyntaxHighlightProcessor</code> classes.
+ */
+public class SyntaxHighlightFactory {
+
+ private static SyntaxHighlightFactory sFactory;
+
+ private final ArrayList<SyntaxHighlightProcessor> mProcessors;
+
+ /**
+ * Constructor of <code>SyntaxHighlightFactory</code>
+ */
+ public SyntaxHighlightFactory() {
+ super();
+ this.mProcessors = new ArrayList<SyntaxHighlightProcessor>();
+ }
+
+ /**
+ * Method that returns the default highlight factory instance
+ *
+ * @param resolver A class for allow the processor to obtain resources
+ * @return SyntaxHighlightFactory The default syntax highlight factory
+ */
+ public static final synchronized SyntaxHighlightFactory getDefaultFactory(
+ ISyntaxHighlightResourcesResolver resolver) {
+ if (sFactory == null) {
+ sFactory = createDefaultFactory(resolver);
+ }
+ return sFactory;
+ }
+
+ /**
+ * Method that returns the syntax highlight processor that can handle the file
+ *
+ * @param file The file to process
+ * @return SyntaxHighlightProcessor The syntax highlight processor
+ */
+ public SyntaxHighlightProcessor getSyntaxHighlightProcessor(File file) {
+ int cc = this.mProcessors.size();
+ for (int i = 0; i < cc; i++) {
+ SyntaxHighlightProcessor processor = this.mProcessors.get(i);
+ if (processor.accept(file)) {
+ return processor;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Method that return all the available syntax highlight processors.
+ *
+ * @return List<SyntaxHighlightProcessor> the list available syntax highlight processors.
+ */
+ public List<SyntaxHighlightProcessor> getAvailableSyntaxHighlightProcessors() {
+ return new ArrayList<SyntaxHighlightProcessor>(this.mProcessors);
+ }
+
+ /**
+ * Method that create the default syntax highlight factory.
+ *
+ * @param resolver A class for allow the processor to obtain resources
+ * @return SyntaxHighlightFactory The default factory
+ */
+ private static SyntaxHighlightFactory createDefaultFactory(
+ ISyntaxHighlightResourcesResolver resolver) {
+ // TODO Read all processors classes of the SPI package
+ // For now we add all known syntax highlight processors
+ SyntaxHighlightFactory factory = new SyntaxHighlightFactory();
+ factory.mProcessors.add(new PropertiesSyntaxHighlightProcessor(resolver));
+ return factory;
+ }
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java
new file mode 100644
index 00000000..2d520346
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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.cyanogenmod.filemanager.ash;
+
+import android.text.Spannable;
+import android.text.Spanned;
+import android.text.style.ForegroundColorSpan;
+
+import java.io.File;
+
+/**
+ * The base class for all the syntax highlight processors.</br>
+ */
+public abstract class SyntaxHighlightProcessor {
+
+ protected final ISyntaxHighlightResourcesResolver mResourcesResolver;
+
+ /**
+ * Constructor of <code>SyntaxHighlightProcessor</code>
+ *
+ * @param resolver A class for resolve resources
+ */
+ public SyntaxHighlightProcessor(ISyntaxHighlightResourcesResolver resolver) {
+ super();
+ this.mResourcesResolver = resolver;
+ }
+
+ /**
+ * Method that request to the syntax highlight processor if it is able to parse
+ * the file
+ *
+ * @param file The file to check
+ * @return boolean If the syntax highlight processor accepts process the file
+ */
+ protected abstract boolean accept(File file);
+
+ /**
+ * Method that initializes the processor
+ */
+ public abstract void initialize();
+
+ /**
+ * Method that request to the syntax highlight processor to do process and highlight a
+ * document. This method request a full process.
+ *
+ * @param spanable The spannable source to highlight
+ */
+ public abstract void process(Spannable spanable);
+
+ /**
+ * Method that request to the syntax highlight processor to process and highlight a
+ * document. This method request a partial process.
+ *
+ * @param spanable The spannable source to highlight
+ * @param start The start of spannable to process
+ * @param end The end of spannable to process
+ */
+ public abstract void process(Spannable spanable, int start, int end);
+
+ /**
+ * Method that cancels the active processor
+ */
+ public abstract void cancel();
+
+ /**
+ * Method that clear all the existent spans
+ *
+ * @param spanable The spannable
+ */
+ @SuppressWarnings("static-method")
+ public void clear(Spannable spanable) {
+ ForegroundColorSpan[] spans =
+ spanable.getSpans(0, spanable.length(), ForegroundColorSpan.class);
+ int cc = spans.length;
+ for (int i = 0; i < cc; i++) {
+ spanable.removeSpan(spans[i]);
+ }
+ }
+
+
+ /**
+ * Method that sets a new <code>Spannable</code>.
+ *
+ * @param spanable The spannable
+ * @param color The color of the span
+ * @param start The start of the span
+ * @param end The end of the span
+ */
+ @SuppressWarnings("static-method")
+ protected void setSpan(Spannable spanable, int color, int start, int end) {
+ if (start == end) return;
+ spanable.setSpan(
+ new ForegroundColorSpan(color),
+ start,
+ end,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java
new file mode 100644
index 00000000..5552b8eb
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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.cyanogenmod.filemanager.ash.scanners;
+
+import java.util.regex.Matcher;
+
+import com.cyanogenmod.filemanager.ash.RegExpUtil;
+
+/**
+ * An scanner to process an input, reporting every text into new lines.
+ */
+public class NewLineScanner extends Scanner {
+
+ private final NewLineScannerListener mListener;
+
+ /**
+ * The listener for the newline scanner
+ */
+ public interface NewLineScannerListener {
+ /**
+ * When a new line is ready
+ *
+ * @param newline The newline detected
+ * @param start The start position of the new line within the input text
+ * @param end The end position of the new line within the input text
+ * @param sep The line separator detected
+ * @return boolean If processor must continue with the next line
+ */
+ boolean onNewLine(CharSequence newline, int start, int end, CharSequence sep);
+ }
+
+ /**
+ * Constructor of <code>Scanner</code>
+ *
+ * @param input The input
+ * @param listener The listener where return every new line
+ */
+ public NewLineScanner(CharSequence input, NewLineScannerListener listener) {
+ super(input);
+ this.mListener = listener;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void scan() {
+ if (this.mInput.length() == 0) return;
+ Matcher m = RegExpUtil.NEWLINE_PATTERN.matcher(this.mInput);
+ int next = 0;
+ while(m.find(next)) {
+ CharSequence line = this.mInput.subSequence(next, m.start());
+ if (!this.mListener.onNewLine(line, next, m.start(), m.group())) {
+ return;
+ }
+ next = m.end();
+ }
+ // The non-matched data
+ CharSequence line = this.mInput.subSequence(next, this.mInput.length());
+ this.mListener.onNewLine(line, next, this.mInput.length(), null);
+ }
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java
new file mode 100644
index 00000000..31583456
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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.cyanogenmod.filemanager.ash.scanners;
+
+
+/**
+ * The base class for all the scanners
+ */
+public abstract class Scanner {
+
+ CharSequence mInput;
+
+ /**
+ * Constructor of <code>Scanner</code>
+ *
+ * @param input The input
+ */
+ public Scanner(CharSequence input) {
+ super();
+ this.mInput = input;
+ }
+
+ /**
+ * Method that starts the scan process
+ */
+ public abstract void scan();
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java
new file mode 100644
index 00000000..f9fd19a2
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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.cyanogenmod.filemanager.ash.spi;
+
+import android.text.Spannable;
+import android.text.style.ForegroundColorSpan;
+
+import com.cyanogenmod.filemanager.ash.HighlightColors;
+import com.cyanogenmod.filemanager.ash.ISyntaxHighlightResourcesResolver;
+import com.cyanogenmod.filemanager.ash.RegExpUtil;
+import com.cyanogenmod.filemanager.ash.SyntaxHighlightProcessor;
+import com.cyanogenmod.filemanager.ash.scanners.NewLineScanner;
+import com.cyanogenmod.filemanager.ash.scanners.NewLineScanner.NewLineScannerListener;
+
+import java.io.File;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A <b>properties</b> highlight processor class.</br>
+ * </br>
+ * The behaviour of this class is:</br>
+ * <ul>
+ * <li>Comments start with # (only spaces are allowed prior to comment)</li>
+ * <li>Assignment character (=) separates key from value</li>
+ * <li>Arguments exists only in values, and are composed by {a digit}</li>
+ * <li>Values can be extended in multiple lines if line ends with the char "\". A
+ * comment in multiline breaks the multiline and starts a new property.</li>
+ * </ul>
+ * </br>
+ * IMP! This class is not thread safe. Calling "process" methods should be
+ * done in a synchronous way.
+ */
+public class PropertiesSyntaxHighlightProcessor extends SyntaxHighlightProcessor {
+
+ private static final String EXT_PROP = "prop"; //$NON-NLS-1$
+ private static final String EXT_PROPERTIES = "properties"; //$NON-NLS-1$
+
+ private static final Pattern COMMENT = Pattern.compile("^\\s*#.*"); //$NON-NLS-1$
+ private static final Pattern MULTILINE = Pattern.compile(".*\\\\\\s*$"); //$NON-NLS-1$
+ private static final Pattern ASSIGNMENT = Pattern.compile("="); //$NON-NLS-1$
+ private static final Pattern ARGUMENT = Pattern.compile("\\{\\d+\\}"); //$NON-NLS-1$
+
+ protected Spannable mSpannable;
+ private boolean mMultiLine;
+
+ private int mKeyColor;
+ private int mAssignmentColor;
+ private int mCommentColor;
+ private int mValueColor;
+ private int mArgumentColor;
+
+ /**
+ * Constructor of <code>PropertiesSyntaxHighlightProcessor</code>
+ *
+ * @param resolver A class for resolve resources
+ */
+ public PropertiesSyntaxHighlightProcessor(ISyntaxHighlightResourcesResolver resolver) {
+ super(resolver);
+ initialize();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean accept(File file) {
+ if (file == null) return false;
+ return file.getName().toLowerCase().endsWith(EXT_PROP) ||
+ file.getName().toLowerCase().endsWith(EXT_PROPERTIES);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void initialize() {
+ this.mMultiLine = false;
+ this.mSpannable = null;
+ if (this.mResourcesResolver != null) {
+ this.mKeyColor = this.mResourcesResolver.getColor(
+ HighlightColors.TEXT.getId(),
+ HighlightColors.TEXT.getResId(),
+ HighlightColors.TEXT.getDefault());
+ this.mAssignmentColor = this.mResourcesResolver.getColor(
+ HighlightColors.ASSIGNMENT.getId(),
+ HighlightColors.ASSIGNMENT.getResId(),
+ HighlightColors.ASSIGNMENT.getDefault());
+ this.mCommentColor = this.mResourcesResolver.getColor(
+ HighlightColors.SINGLE_LINE_COMMENT.getId(),
+ HighlightColors.SINGLE_LINE_COMMENT.getResId(),
+ HighlightColors.SINGLE_LINE_COMMENT.getDefault());
+ this.mValueColor = this.mResourcesResolver.getColor(
+ HighlightColors.VARIABLE.getId(),
+ HighlightColors.VARIABLE.getResId(),
+ HighlightColors.VARIABLE.getDefault());
+ this.mArgumentColor = this.mResourcesResolver.getColor(
+ HighlightColors.KEYWORD.getId(),
+ HighlightColors.KEYWORD.getResId(),
+ HighlightColors.KEYWORD.getDefault());
+ } else {
+ // By default
+ this.mKeyColor = HighlightColors.TEXT.getDefault();
+ this.mAssignmentColor = HighlightColors.TEXT.getDefault();
+ this.mCommentColor = HighlightColors.SINGLE_LINE_COMMENT.getDefault();
+ this.mValueColor = HighlightColors.VARIABLE.getDefault();
+ this.mArgumentColor = HighlightColors.KEYWORD.getDefault();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void process(final Spannable spanable) {
+ this.mMultiLine = false;
+ this.mSpannable = spanable;
+ clear(spanable);
+ NewLineScanner scanner = new NewLineScanner(spanable, new NewLineScannerListener() {
+ @Override
+ public boolean onNewLine(CharSequence newline, int start, int end, CharSequence sep) {
+ processNewLine(newline, start, end);
+ return true;
+ }
+
+ });
+ scanner.scan();
+ this.mSpannable = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void process(final Spannable spanable, final int start, final int end) {
+ // We need a Retrieve the previous line
+ this.mMultiLine = false;
+ this.mSpannable = spanable;
+ CharSequence seqs = spanable.subSequence(0, start);
+ CharSequence seqe = spanable.subSequence(end, spanable.length());
+ int s1 = RegExpUtil.getLastMatch(RegExpUtil.NEWLINE_PATTERN, seqs, false);
+ if (s1 == RegExpUtil.NO_MATCH) {
+ s1 = 0;
+ }
+ int e1 = RegExpUtil.getNextMatch(RegExpUtil.NEWLINE_PATTERN, seqe, false);
+ if (e1 == RegExpUtil.NO_MATCH) {
+ e1 = spanable.length();
+ } else {
+ e1 += end;
+ }
+
+ // Also, we need to know about if the previous line is multiline
+ if (s1 > 0) {
+ int s2 = RegExpUtil.getLastMatch(RegExpUtil.NEWLINE_PATTERN, seqs, true);
+ CharSequence seqnl = spanable.subSequence(0, s2);
+ int snl = RegExpUtil.getLastMatch(RegExpUtil.NEWLINE_PATTERN, seqnl, false);
+ Matcher mlm = MULTILINE.matcher(
+ spanable.subSequence(snl != RegExpUtil.NO_MATCH ? snl : 0, s2));
+ this.mMultiLine = mlm.matches();
+ }
+
+ // Process the new line
+ if (s1 != e1) {
+ processNewLine(spanable.subSequence(s1, e1), s1, e1);
+ }
+
+ // Now, multiline again (next line). We check always the next line, because we
+ // don't know if user delete multiline flag in the current line
+ e1 = RegExpUtil.getNextMatch(RegExpUtil.NEWLINE_PATTERN, seqe, true);
+ if (e1 != RegExpUtil.NO_MATCH) {
+ e1 += end;
+ seqe = spanable.subSequence(e1, spanable.length());
+ int e2 = RegExpUtil.getNextMatch(RegExpUtil.NEWLINE_PATTERN, seqe, false);
+ if (e2 == RegExpUtil.NO_MATCH) {
+ e2 = spanable.length();
+ } else {
+ e2 += e1;
+ }
+ processNewLine(spanable.subSequence(e1, e2), e1, e2);
+ }
+
+ this.mSpannable = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void cancel() {
+ // Not needed by this processor
+ }
+
+ /**
+ * A method to process every new line
+ *
+ * @param newline The newline
+ * @param start The start position of the line
+ * @param end The end position of the line
+ * @hide
+ */
+ void processNewLine(CharSequence newline, int start, int end) {
+ // Remove all spannable of the line (this processor doesn't multiline spans and
+ // only uses ForegroundColorSpan spans)
+ ForegroundColorSpan[] spans =
+ this.mSpannable.getSpans(start, end, ForegroundColorSpan.class);
+ int cc = spans.length;
+ for (int i = 0; i < cc; i++) {
+ this.mSpannable.removeSpan(spans[i]);
+ }
+
+ // Find comment
+ Matcher cm = COMMENT.matcher(newline);
+ if (cm.matches()) {
+ // All the line is a comment
+ setSpan(this.mSpannable, this.mCommentColor, start, end);
+ this.mMultiLine = false;
+ return;
+ }
+
+ // Has multiline
+ Matcher mlm = MULTILINE.matcher(newline);
+ boolean ml = mlm.matches();
+
+ //Find the assignment
+ int k = this.mMultiLine ? -1 : start;
+ int v = start;
+ int v2 = 0;
+ int a = -1;
+ if (!this.mMultiLine) {
+ Matcher am = ASSIGNMENT.matcher(newline);
+ if (am.find()) {
+ // Assignment found
+ v2 = am.start() + 1;
+ a = start + am.start();
+ v = a + 1;
+ }
+ }
+
+ // All the string is a key
+ if (!this.mMultiLine && a == -1) {
+ setSpan(this.mSpannable, this.mKeyColor, start, end);
+
+ } else {
+ // Key
+ if (!this.mMultiLine) {
+ setSpan(this.mSpannable, this.mKeyColor, k, a);
+ }
+ // Assignment
+ if (!this.mMultiLine) {
+ setSpan(this.mSpannable, this.mAssignmentColor, a, a + 1);
+ }
+ // Value
+ setSpan(this.mSpannable, this.mValueColor, v, end);
+ // Argument
+ Matcher argm = ARGUMENT.matcher(newline);
+ while (argm.find(v2)) {
+ int s = start + argm.start();
+ int e = start + argm.end();
+ setSpan(this.mSpannable, this.mArgumentColor, s, e);
+ v2 = argm.end();
+ }
+ }
+
+ // Multiline?
+ this.mMultiLine = ml;
+ }
+}
diff --git a/libs/color-picker-view/CHANGELOG.md b/libs/color-picker-view/CHANGELOG.md
new file mode 100644
index 00000000..342ba60e
--- /dev/null
+++ b/libs/color-picker-view/CHANGELOG.md
@@ -0,0 +1,4 @@
+ChangeLog
+========================
+
+The source was grabbed from version 1.0 (r8)
diff --git a/libs/color-picker-view/LICENSE.md b/libs/color-picker-view/LICENSE.md
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/libs/color-picker-view/LICENSE.md
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ 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.
diff --git a/libs/color-picker-view/README.md b/libs/color-picker-view/README.md
new file mode 100644
index 00000000..b26ef5aa
--- /dev/null
+++ b/libs/color-picker-view/README.md
@@ -0,0 +1,18 @@
+mColorPicker
+================================
+
+A color picker is something that has always been missing from the standard
+set of components which developers can build their user interface in Android
+with. Although there have been a few color pickers floating around on the
+internet I never found any that I thought was good enough for use in my
+applications so I sat down to write my own. This is the result and I have
+decided to release it as open source application for all you developers
+out there to use, free of charge of course.
+
+Checkout latest sources at http://code.google.com/p/color-picker-view/
+
+This library is released under the [Apache 2.0]
+http://www.apache.org/licenses/LICENSE-2.0.html) license.
+
+Copyright © 2010 Daniel Nilsson
+Copyright © 2013 The CyanogenMod Project
diff --git a/libs/color-picker-view/src/afzkl/development/mColorPicker/drawables/AlphaPatternDrawable.java b/libs/color-picker-view/src/afzkl/development/mColorPicker/drawables/AlphaPatternDrawable.java
new file mode 100644
index 00000000..e878756d
--- /dev/null
+++ b/libs/color-picker-view/src/afzkl/development/mColorPicker/drawables/AlphaPatternDrawable.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 Daniel Nilsson
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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 afzkl.development.mColorPicker.drawables;
+
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+/**
+ * This drawable that draws a simple white and gray chessboard pattern.
+ * It's pattern you will often see as a background behind a
+ * partly transparent image in many applications.
+ * @author Daniel Nilsson
+ */
+@SuppressWarnings("all")
+public class AlphaPatternDrawable extends Drawable {
+
+ private int mRectangleSize = 10;
+
+ private final Paint mPaint = new Paint();
+ private final Paint mPaintWhite = new Paint();
+ private final Paint mPaintGray = new Paint();
+
+ private int numRectanglesHorizontal;
+ private int numRectanglesVertical;
+
+ /**
+ * Bitmap in which the pattern will be cahched.
+ */
+ private Bitmap mBitmap;
+
+ public AlphaPatternDrawable(int rectangleSize) {
+ mRectangleSize = rectangleSize;
+ mPaintWhite.setColor(0xffffffff);
+ mPaintGray.setColor(0xffcbcbcb);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.drawBitmap(mBitmap, null, getBounds(), mPaint);
+ }
+
+ @Override
+ public int getOpacity() {
+ return 0;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ throw new UnsupportedOperationException("Alpha is not supported by this drawwable.");
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ throw new UnsupportedOperationException("ColorFilter is not supported by this drawwable.");
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ super.onBoundsChange(bounds);
+
+ int height = bounds.height();
+ int width = bounds.width();
+
+ numRectanglesHorizontal = (int) Math.ceil((width / mRectangleSize));
+ numRectanglesVertical = (int) Math.ceil(height / mRectangleSize);
+
+ generatePatternBitmap();
+
+ }
+
+ /**
+ * This will generate a bitmap with the pattern
+ * as big as the rectangle we were allow to draw on.
+ * We do this to chache the bitmap so we don't need to
+ * recreate it each time draw() is called since it
+ * takes a few milliseconds.
+ */
+ private void generatePatternBitmap() {
+
+ if (getBounds().width() <= 0 || getBounds().height() <= 0) {
+ return;
+ }
+
+ mBitmap = Bitmap.createBitmap(getBounds().width(), getBounds().height(), Config.ARGB_8888);
+ Canvas canvas = new Canvas(mBitmap);
+
+ Rect r = new Rect();
+ boolean verticalStartWhite = true;
+ for (int i = 0; i <= numRectanglesVertical; i++) {
+
+ boolean isWhite = verticalStartWhite;
+ for (int j = 0; j <= numRectanglesHorizontal; j++) {
+
+ r.top = i * mRectangleSize;
+ r.left = j * mRectangleSize;
+ r.bottom = r.top + mRectangleSize;
+ r.right = r.left + mRectangleSize;
+
+ canvas.drawRect(r, isWhite ? mPaintWhite : mPaintGray);
+
+ isWhite = !isWhite;
+ }
+
+ verticalStartWhite = !verticalStartWhite;
+
+ }
+
+ }
+
+}
diff --git a/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorDialogView.java b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorDialogView.java
new file mode 100644
index 00000000..d35becf2
--- /dev/null
+++ b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorDialogView.java
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2013 Jorge Ruesga
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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 afzkl.development.mColorPicker.views;
+
+import afzkl.development.mColorPicker.views.ColorPickerView.OnColorChangedListener;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.InputType;
+import android.text.Spanned;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+/**
+ * A view use directly into a dialog. It contains a one {@link ColorPickerView}
+ * and two {@link ColorPanelView} (the current color and the new color)
+ */
+public class ColorDialogView extends RelativeLayout
+ implements OnColorChangedListener, TextWatcher {
+
+ private static final int DEFAULT_MARGIN_DP = 16;
+ private static final int DEFAULT_PANEL_HEIGHT_DP = 32;
+ private static final int DEFAULT_TEXT_SIZE_SP = 12;
+ private static final int DEFAULT_LABEL_TEXT_SIZE_SP = 18;
+
+ private ColorPickerView mPickerView;
+ private ColorPanelView mCurrentColorView;
+ private ColorPanelView mNewColorView;
+ private TextView tvCurrent;
+ private TextView tvNew;
+ private TextView tvColorLabel;
+ private EditText etColor;
+
+ private String mCurrentLabelText = "Current:"; //$NON-NLS-1$
+ private String mNewLabelText = "New:"; //$NON-NLS-1$
+
+ private String mColorLabelText = "Color:"; //$NON-NLS-1$
+
+ /**
+ * Constructor of <code>ColorDialogView</code>
+ *
+ * @param context The current context
+ */
+ public ColorDialogView(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Constructor of <code>ColorDialogView</code>
+ *
+ * @param context The current context
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ */
+ public ColorDialogView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ /**
+ * Constructor of <code>ColorDialogView</code>
+ *
+ * @param context The current context
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ * @param defStyle The default style to apply to this view. If 0, no style
+ * will be applied (beyond what is included in the theme). This may
+ * either be an attribute resource, whose value will be retrieved
+ * from the current theme, or an explicit style resource.
+ */
+ public ColorDialogView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ /**
+ * Method that initializes the view. This method loads all the necessary
+ * information and create an appropriate layout for the view
+ */
+ private void init() {
+ // To fight color branding.
+ ((Activity)getContext()).getWindow().setFormat(PixelFormat.RGBA_8888);
+
+ // Creates the color input field
+ int id = createColorInput();
+
+ // Creates the color picker
+ id = createColorPicker(id);
+
+ // Creates the current color and new color panels
+ id = createColorsPanel(id);
+
+ // Sets the input color
+ this.etColor.setText(toHex(this.mNewColorView.getColor()));
+ }
+
+ /**
+ * Method that creates the color input
+ */
+ private int createColorInput() {
+ final int dlgMarging = (int)convertDpToPixel(DEFAULT_MARGIN_DP);
+ LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT);
+ lp2.setMargins(0, 0, dlgMarging, 0);
+ this.tvColorLabel = new TextView(getContext());
+ this.tvColorLabel.setText(this.mColorLabelText);
+ this.tvColorLabel.setTextSize(TypedValue.COMPLEX_UNIT_SP, DEFAULT_LABEL_TEXT_SIZE_SP);
+ this.tvColorLabel.setGravity(Gravity.BOTTOM | Gravity.LEFT);
+ this.tvColorLabel.setLayoutParams(lp2);
+
+ lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
+ this.etColor = new EditText(getContext());
+ this.etColor.setSingleLine();
+ this.etColor.setGravity(Gravity.TOP | Gravity.LEFT);
+ this.etColor.setCursorVisible(true);
+ this.etColor.setImeOptions(
+ EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_FULLSCREEN);
+ this.etColor.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+ this.etColor.setLayoutParams(lp2);
+ InputFilter[] filters = new InputFilter[2];
+ filters[0] = new InputFilter.LengthFilter(8);
+ filters[1] = new InputFilter() {
+ @Override
+ public CharSequence filter(CharSequence source, int start,
+ int end, Spanned dest, int dstart, int dend) {
+ if (start >= end) return ""; //$NON-NLS-1$
+ String s = source.subSequence(start, end).toString();
+ StringBuilder sb = new StringBuilder();
+ int cc = s.length();
+ for (int i = 0; i < cc; i++) {
+ char c = s.charAt(i);
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F')) {
+ sb.append(c);
+ }
+ }
+ return sb.toString().toUpperCase();
+ }
+ };
+ this.etColor.setFilters(filters);
+ this.etColor.addTextChangedListener(this);
+
+ LinearLayout ll1 = new LinearLayout(getContext());
+ ll1.setId(generateViewId());
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
+ lp.setMargins(dlgMarging, 0, dlgMarging, 0);
+ lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ ll1.setLayoutParams(lp);
+ ll1.addView(this.tvColorLabel);
+ ll1.addView(this.etColor);
+ addView(ll1);
+
+ return ll1.getId();
+ }
+
+ /**
+ * Method that creates the color picker
+ *
+ * @param belowOf The anchor view
+ * @return id The layout id
+ */
+ private int createColorPicker(int belowOf) {
+ final int dlgMarging = (int)convertDpToPixel(DEFAULT_MARGIN_DP);
+ this.mPickerView = new ColorPickerView(getContext());
+ this.mPickerView.setId(generateViewId());
+ this.mPickerView.setOnColorChangedListener(this);
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
+ lp.setMargins(dlgMarging, 0, dlgMarging, 0);
+ lp.addRule(RelativeLayout.BELOW, belowOf);
+ this.mPickerView.setLayoutParams(lp);
+ addView(this.mPickerView);
+ return this.mPickerView.getId();
+ }
+
+ /**
+ * Method that creates the colors panel (current and new)
+ *
+ * @param belowOf The anchor view
+ * @return id The layout id
+ */
+ private int createColorsPanel(int belowOf) {
+ final int dlgMarging = (int)convertDpToPixel(DEFAULT_MARGIN_DP);
+ final int panelHeight = (int)convertDpToPixel(DEFAULT_PANEL_HEIGHT_DP);
+ LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ 1);
+
+ // Titles
+ this.tvCurrent = new TextView(getContext());
+ lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ 1);
+ this.tvCurrent.setLayoutParams(lp2);
+ this.tvCurrent.setText(this.mCurrentLabelText);
+ this.tvCurrent.setTextSize(TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE_SP);
+ this.tvNew = new TextView(getContext());
+ this.tvNew.setLayoutParams(lp2);
+ this.tvNew.setText(this.mNewLabelText);
+ this.tvNew.setTextSize(TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE_SP);
+ TextView sep1 = new TextView(getContext());
+ lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ 0);
+ lp2.setMargins(dlgMarging, 0, dlgMarging, 0);
+ sep1.setLayoutParams(lp2);
+ sep1.setText(" "); //$NON-NLS-1$
+ sep1.setTextSize(TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE_SP);
+
+ LinearLayout ll1 = new LinearLayout(getContext());
+ ll1.setId(generateViewId());
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
+ lp.setMargins(dlgMarging, 0, dlgMarging, dlgMarging/2);
+ lp.addRule(RelativeLayout.BELOW, belowOf);
+ ll1.setLayoutParams(lp);
+ ll1.addView(this.tvCurrent);
+ ll1.addView(sep1);
+ ll1.addView(this.tvNew);
+ addView(ll1);
+
+ // Color panels
+ lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ 1);
+ this.mCurrentColorView = new ColorPanelView(getContext());
+ this.mCurrentColorView.setLayoutParams(lp2);
+ this.mNewColorView = new ColorPanelView(getContext());
+ this.mNewColorView.setLayoutParams(lp2);
+ TextView sep2 = new TextView(getContext());
+ lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ 0);
+ lp2.setMargins(dlgMarging, 0, dlgMarging, 0);
+ sep2.setLayoutParams(lp2);
+ sep2.setText("-"); //$NON-NLS-1$
+ sep2.setTextSize(TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE_SP);
+
+ LinearLayout ll2 = new LinearLayout(getContext());
+ ll2.setId(generateViewId());
+ lp = new RelativeLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT, panelHeight);
+ lp.setMargins(dlgMarging, 0, dlgMarging, dlgMarging/2);
+ lp.addRule(RelativeLayout.BELOW, ll1.getId());
+ ll2.setLayoutParams(lp);
+ ll2.addView(this.mCurrentColorView);
+ ll2.addView(sep2);
+ ll2.addView(this.mNewColorView);
+ addView(ll2);
+
+ return ll2.getId();
+ }
+
+ /**
+ * Method that returns the color of the picker
+ *
+ * @return The ARGB color
+ */
+ public int getColor() {
+ return this.mPickerView.getColor();
+ }
+
+ /**
+ * Method that set the color of the picker
+ *
+ * @param argb The ARGB color
+ */
+ public void setColor(int argb) {
+ setColor(argb, false);
+ }
+
+ /**
+ * Method that set the color of the picker
+ *
+ * @param argb The ARGB color
+ * @param fromEditText If the call comes from the <code>EditText</code>
+ */
+ private void setColor(int argb, boolean fromEditText) {
+ this.mPickerView.setColor(argb, false);
+ this.mCurrentColorView.setColor(argb);
+ this.mNewColorView.setColor(argb);
+ if (!fromEditText) {
+ this.etColor.setText(toHex(this.mNewColorView.getColor()));
+ }
+ }
+
+ /**
+ * Method that display/hide the alpha slider
+ *
+ * @param show If the alpha slider should be shown
+ */
+ public void showAlphaSlider(boolean show) {
+ this.mPickerView.setAlphaSliderVisible(show);
+ }
+
+ /**
+ * Set the text that should be shown in the alpha slider.
+ * Set to null to disable text.
+ *
+ * @param text Text that should be shown.
+ */
+ public void setAlphaSliderText(String text) {
+ this.mPickerView.setAlphaSliderText(text);
+ }
+
+ /**
+ * Set the text that should be shown in the actual color panel.
+ * Set to null to disable text.
+ *
+ * @param text Text that should be shown.
+ */
+ public void setCurrentColorText(String text) {
+ this.mCurrentLabelText = text;
+ this.tvCurrent.setText(this.mCurrentLabelText);
+ }
+
+ /**
+ * Set the text that should be shown in the new color panel.
+ * Set to null to disable text.
+ *
+ * @param text Text that should be shown.
+ */
+ public void setNewColorText(String text) {
+ this.mNewLabelText = text;
+ this.tvNew.setText(this.mNewLabelText);
+ }
+
+ /**
+ * Set the text that should be shown in the label of the color input.
+ * Set to null to disable text.
+ *
+ * @param text Text that should be shown.
+ */
+ public void setColorLabelText(String text) {
+ this.mColorLabelText = text;
+ this.tvColorLabel.setText(this.mColorLabelText);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onColorChanged(int color) {
+ this.mNewColorView.setColor(color);
+ this.etColor.removeTextChangedListener(this);
+ this.etColor.setText(toHex(this.mNewColorView.getColor()));
+ this.etColor.addTextChangedListener(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {/**NON BLOCK**/}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {/**NON BLOCK**/}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (s.length() == 8) {
+ try {
+ setColor(toARGB(s.toString()), true);
+ } catch (Exception e) {/**NON BLOCK**/}
+ }
+ }
+
+ /**
+ * This method converts dp unit to equivalent device specific value in pixels.
+ *
+ * @param ctx The current context
+ * @param dp A value in dp (Device independent pixels) unit
+ * @return float A float value to represent Pixels equivalent to dp according to device
+ */
+ private float convertDpToPixel(float dp) {
+ Resources resources = getContext().getResources();
+ DisplayMetrics metrics = resources.getDisplayMetrics();
+ return dp * (metrics.densityDpi / 160f);
+ }
+
+ /**
+ * Method that converts an ARGB color to its hex string color representation
+ *
+ * @param argb The ARGB color
+ * @return String The hex string representation of the color
+ */
+ private static String toHex(int argb) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(toHexString((byte)Color.alpha(argb)));
+ sb.append(toHexString((byte)Color.red(argb)));
+ sb.append(toHexString((byte)Color.green(argb)));
+ sb.append(toHexString((byte)Color.blue(argb)));
+ return sb.toString();
+ }
+
+ /**
+ * Method that converts an hex string color representation to an ARGB color
+ *
+ * @param hex The hex string representation of the color
+ * @return int The ARGB color
+ */
+ private static int toARGB(String hex) {
+ return Color.parseColor("#" + hex); //$NON-NLS-1$
+ }
+
+ /**
+ * Method that converts a byte into its hex string representation
+ *
+ * @param v The value to convert
+ * @return String The hex string representation
+ */
+ private static String toHexString(byte v) {
+ String hex = Integer.toHexString(v & 0xff);
+ if (hex.length() == 1) {
+ hex = "0" + hex; //$NON-NLS-1$
+ }
+ return hex.toUpperCase();
+ }
+}
diff --git a/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPanelView.java b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPanelView.java
new file mode 100644
index 00000000..9764ff1d
--- /dev/null
+++ b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPanelView.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2010 Daniel Nilsson
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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 afzkl.development.mColorPicker.views;
+
+import afzkl.development.mColorPicker.drawables.AlphaPatternDrawable;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * This class draws a panel which which will be filled with a color which can be set.
+ * It can be used to show the currently selected color which you will get from
+ * the {@link ColorPickerView}.
+ * @author Daniel Nilsson
+ *
+ */
+@SuppressWarnings("all")
+public class ColorPanelView extends View{
+
+ /**
+ * The width in pixels of the border
+ * surrounding the color panel.
+ */
+ private final static float BORDER_WIDTH_PX = 1;
+
+ private static float mDensity = 1f;
+
+ private int mBorderColor = 0xff6E6E6E;
+ private int mColor = 0xff000000;
+
+ private Paint mBorderPaint;
+ private Paint mColorPaint;
+
+ private RectF mDrawingRect;
+ private RectF mColorRect;
+
+ private AlphaPatternDrawable mAlphaPattern;
+
+
+ public ColorPanelView(Context context) {
+ this(context, null);
+ }
+
+ public ColorPanelView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ColorPanelView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ init();
+ }
+
+ private void init() {
+ mBorderPaint = new Paint();
+ mColorPaint = new Paint();
+ mDensity = getContext().getResources().getDisplayMetrics().density;
+ }
+
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+
+ final RectF rect = mColorRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(mDrawingRect, mBorderPaint);
+ }
+
+ if (mAlphaPattern != null) {
+ mAlphaPattern.draw(canvas);
+ }
+
+ mColorPaint.setColor(mColor);
+
+ canvas.drawRect(rect, mColorPaint);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ setMeasuredDimension(width, height);
+ }
+
+ @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.right = w - getPaddingRight();
+ mDrawingRect.top = getPaddingTop();
+ mDrawingRect.bottom = h - getPaddingBottom();
+
+ setUpColorRect();
+
+ }
+
+ private void setUpColorRect() {
+ final RectF dRect = mDrawingRect;
+
+ 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;
+
+ 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),
+ Math.round(mColorRect.bottom));
+
+ }
+
+ /**
+ * Set the color that should be shown by this view.
+ * @param color
+ */
+ public void setColor(int color) {
+ mColor = color;
+ invalidate();
+ }
+
+ /**
+ * Get the color currently show by this view.
+ * @return
+ */
+ public int getColor() {
+ return mColor;
+ }
+
+ /**
+ * Set the color of the border surrounding the panel.
+ * @param color
+ */
+ public void setBorderColor(int color) {
+ mBorderColor = color;
+ invalidate();
+ }
+
+ /**
+ * Get the color of the border surrounding the panel.
+ */
+ public int getBorderColor() {
+ return mBorderColor;
+ }
+
+}
diff --git a/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPickerView.java b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPickerView.java
new file mode 100644
index 00000000..eb216c88
--- /dev/null
+++ b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPickerView.java
@@ -0,0 +1,998 @@
+/*
+ * Copyright (C) 2010 Daniel Nilsson
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 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 afzkl.development.mColorPicker.views;
+
+import afzkl.development.mColorPicker.drawables.AlphaPatternDrawable;
+
+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.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.Shader.TileMode;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.lang.reflect.Method;
+
+/**
+ * Displays a color picker to the user and allow them
+ * to select a color. A slider for the alpha channel is
+ * also available. Enable it by setting
+ * setAlphaSliderVisible(boolean) to true.
+ * @author Daniel Nilsson
+ */
+@SuppressWarnings("all")
+public class ColorPickerView extends View{
+
+ public interface OnColorChangedListener{
+ public void onColorChanged(int color);
+ }
+
+ private final static int PANEL_SAT_VAL = 0;
+ private final static int PANEL_HUE = 1;
+ private final static int PANEL_ALPHA = 2;
+
+ /**
+ * The width in pixels of the border
+ * surrounding all color panels.
+ */
+ private final static float BORDER_WIDTH_PX = 1;
+
+ /**
+ * The width in dp of the hue panel.
+ */
+ private float HUE_PANEL_WIDTH = 30f;
+ /**
+ * The height in dp of the alpha panel
+ */
+ private float ALPHA_PANEL_HEIGHT = 20f;
+ /**
+ * The distance in dp between the different
+ * color panels.
+ */
+ private float PANEL_SPACING = 10f;
+ /**
+ * The radius in dp of the color palette tracker circle.
+ */
+ private float PALETTE_CIRCLE_TRACKER_RADIUS = 5f;
+ /**
+ * The dp which the tracker of the hue or alpha panel
+ * will extend outside of its bounds.
+ */
+ private float RECTANGLE_TRACKER_OFFSET = 2f;
+
+
+ private static float mDensity = 1f;
+
+ private OnColorChangedListener mListener;
+
+ private Paint mSatValPaint;
+ private Paint mSatValTrackerPaint;
+
+ private Paint mHuePaint;
+ private Paint mHueTrackerPaint;
+
+ private Paint mAlphaPaint;
+ private Paint mAlphaTextPaint;
+
+ private Paint mBorderPaint;
+
+ private Shader mValShader;
+ private Shader mSatShader;
+ private Shader mHueShader;
+ private Shader mAlphaShader;
+
+ private int mAlpha = 0xff;
+ private float mHue = 360f;
+ private float mSat = 0f;
+ private float mVal = 0f;
+
+ private String mAlphaSliderText = "Alpha";
+ private int mSliderTrackerColor = 0xff1c1c1c;
+ private int mBorderColor = 0xff6E6E6E;
+ private boolean mShowAlphaPanel = false;
+
+ /*
+ * To remember which panel that has the "focus" when
+ * processing hardware button data.
+ */
+ private int mLastTouchedPanel = PANEL_SAT_VAL;
+
+ /**
+ * Offset from the edge we must have or else
+ * the finger tracker will get clipped when
+ * it is drawn outside of the view.
+ */
+ private float mDrawingOffset;
+
+
+ /*
+ * Distance form the edges of the view
+ * of where we are allowed to draw.
+ */
+ private RectF mDrawingRect;
+
+ private RectF mSatValRect;
+ private RectF mHueRect;
+ private RectF mAlphaRect;
+
+ private AlphaPatternDrawable mAlphaPattern;
+
+ private Point mStartTouchPoint = null;
+
+
+ public ColorPickerView(Context context) {
+ this(context, null);
+ }
+
+ public ColorPickerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ColorPickerView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ mDensity = getContext().getResources().getDisplayMetrics().density;
+ PALETTE_CIRCLE_TRACKER_RADIUS *= mDensity;
+ RECTANGLE_TRACKER_OFFSET *= mDensity;
+ HUE_PANEL_WIDTH *= mDensity;
+ ALPHA_PANEL_HEIGHT *= mDensity;
+ PANEL_SPACING = PANEL_SPACING * mDensity;
+
+ mDrawingOffset = calculateRequiredOffset();
+
+ initPaintTools();
+
+ //Needed for receiving trackball motion events.
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ }
+
+ private void initPaintTools() {
+
+ mSatValPaint = new Paint();
+ mSatValTrackerPaint = new Paint();
+ mHuePaint = new Paint();
+ mHueTrackerPaint = new Paint();
+ mAlphaPaint = new Paint();
+ mAlphaTextPaint = new Paint();
+ mBorderPaint = new Paint();
+
+
+ mSatValTrackerPaint.setStyle(Style.STROKE);
+ mSatValTrackerPaint.setStrokeWidth(2f * mDensity);
+ mSatValTrackerPaint.setAntiAlias(true);
+
+ mHueTrackerPaint.setColor(mSliderTrackerColor);
+ mHueTrackerPaint.setStyle(Style.STROKE);
+ mHueTrackerPaint.setStrokeWidth(2f * mDensity);
+ mHueTrackerPaint.setAntiAlias(true);
+
+ mAlphaTextPaint.setColor(0xff1c1c1c);
+ mAlphaTextPaint.setTextSize(14f * mDensity);
+ mAlphaTextPaint.setAntiAlias(true);
+ mAlphaTextPaint.setTextAlign(Align.CENTER);
+ mAlphaTextPaint.setFakeBoldText(true);
+
+
+ }
+
+ private float calculateRequiredOffset() {
+ float offset = Math.max(PALETTE_CIRCLE_TRACKER_RADIUS, RECTANGLE_TRACKER_OFFSET);
+ offset = Math.max(offset, BORDER_WIDTH_PX * mDensity);
+
+ return offset * 1.5f;
+ }
+
+ private int[] buildHueColorArray() {
+
+ int[] hue = new int[361];
+
+ int count = 0;
+ for (int i = hue.length -1; i >= 0; i--, count++) {
+ hue[count] = Color.HSVToColor(new float[]{i, 1f, 1f});
+ }
+
+ return hue;
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ checkHardwareAccelerationSupport();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+
+ if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0) return;
+
+ drawSatValPanel(canvas);
+ drawHuePanel(canvas);
+ drawAlphaPanel(canvas);
+
+ }
+
+ private void drawSatValPanel(Canvas canvas) {
+
+ final RectF rect = mSatValRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(mDrawingRect.left, mDrawingRect.top, rect.right + BORDER_WIDTH_PX, rect.bottom + BORDER_WIDTH_PX, mBorderPaint);
+ }
+
+ if (mValShader == null) {
+ mValShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
+ 0xffffffff, 0xff000000, TileMode.CLAMP);
+ }
+
+ int rgb = Color.HSVToColor(new float[]{mHue,1f,1f});
+
+ mSatShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
+ 0xffffffff, rgb, TileMode.CLAMP);
+ ComposeShader mShader = new ComposeShader(mValShader, mSatShader, PorterDuff.Mode.MULTIPLY);
+ mSatValPaint.setShader(mShader);
+
+ canvas.drawRect(rect, mSatValPaint);
+
+ Point p = satValToPoint(mSat, mVal);
+
+ mSatValTrackerPaint.setColor(0xff000000);
+ canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS - 1f * mDensity, mSatValTrackerPaint);
+
+ mSatValTrackerPaint.setColor(0xffdddddd);
+ canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS, mSatValTrackerPaint);
+
+ }
+
+ private void drawHuePanel(Canvas canvas) {
+
+ final RectF rect = mHueRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(rect.left - BORDER_WIDTH_PX,
+ rect.top - BORDER_WIDTH_PX,
+ rect.right + BORDER_WIDTH_PX,
+ rect.bottom + BORDER_WIDTH_PX,
+ mBorderPaint);
+ }
+
+ if (mHueShader == null) {
+ mHueShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom, buildHueColorArray(), null, TileMode.CLAMP);
+ mHuePaint.setShader(mHueShader);
+ }
+
+ canvas.drawRect(rect, mHuePaint);
+
+ float rectHeight = 4 * mDensity / 2;
+
+ Point p = hueToPoint(mHue);
+
+ RectF r = new RectF();
+ r.left = rect.left - RECTANGLE_TRACKER_OFFSET;
+ r.right = rect.right + RECTANGLE_TRACKER_OFFSET;
+ r.top = p.y - rectHeight;
+ r.bottom = p.y + rectHeight;
+
+
+ canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
+
+ }
+
+ private void drawAlphaPanel(Canvas canvas) {
+
+ if (!mShowAlphaPanel || mAlphaRect == null || mAlphaPattern == null) return;
+
+ final RectF rect = mAlphaRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(rect.left - BORDER_WIDTH_PX,
+ rect.top - BORDER_WIDTH_PX,
+ rect.right + BORDER_WIDTH_PX,
+ rect.bottom + BORDER_WIDTH_PX,
+ mBorderPaint);
+ }
+
+
+ mAlphaPattern.draw(canvas);
+
+ float[] hsv = new float[]{mHue,mSat,mVal};
+ int color = Color.HSVToColor(hsv);
+ int acolor = Color.HSVToColor(0, hsv);
+
+ mAlphaShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
+ color, acolor, TileMode.CLAMP);
+
+
+ mAlphaPaint.setShader(mAlphaShader);
+
+ canvas.drawRect(rect, mAlphaPaint);
+
+ if (mAlphaSliderText != null && mAlphaSliderText!= "") {
+ canvas.drawText(mAlphaSliderText, rect.centerX(), rect.centerY() + 4 * mDensity, mAlphaTextPaint);
+ }
+
+ float rectWidth = 4 * mDensity / 2;
+
+ Point p = alphaToPoint(mAlpha);
+
+ RectF r = new RectF();
+ r.left = p.x - rectWidth;
+ r.right = p.x + rectWidth;
+ r.top = rect.top - RECTANGLE_TRACKER_OFFSET;
+ r.bottom = rect.bottom + RECTANGLE_TRACKER_OFFSET;
+
+ canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
+
+ }
+
+
+ private Point hueToPoint(float hue) {
+
+ final RectF rect = mHueRect;
+ final float height = rect.height();
+
+ Point p = new Point();
+
+ p.y = (int) (height - (hue * height / 360f) + rect.top);
+ p.x = (int) rect.left;
+
+ return p;
+ }
+
+ private Point satValToPoint(float sat, float val) {
+
+ final RectF rect = mSatValRect;
+ final float height = rect.height();
+ final float width = rect.width();
+
+ Point p = new Point();
+
+ p.x = (int) (sat * width + rect.left);
+ p.y = (int) ((1f - val) * height + rect.top);
+
+ return p;
+ }
+
+ private Point alphaToPoint(int alpha) {
+
+ final RectF rect = mAlphaRect;
+ final float width = rect.width();
+
+ Point p = new Point();
+
+ p.x = (int) (width - (alpha * width / 0xff) + rect.left);
+ p.y = (int) rect.top;
+
+ return p;
+
+ }
+
+ private float[] pointToSatVal(float x, float y) {
+
+ final RectF rect = mSatValRect;
+ float[] result = new float[2];
+
+ float width = rect.width();
+ float height = rect.height();
+
+ if (x < rect.left) {
+ x = 0f;
+ }
+ else if (x > rect.right) {
+ x = width;
+ }
+ else{
+ x = x - rect.left;
+ }
+
+ if (y < rect.top) {
+ y = 0f;
+ }
+ else if (y > rect.bottom) {
+ y = height;
+ }
+ else{
+ y = y - rect.top;
+ }
+
+
+ result[0] = 1.f / width * x;
+ result[1] = 1.f - (1.f / height * y);
+
+ return result;
+ }
+
+ private float pointToHue(float y) {
+
+ final RectF rect = mHueRect;
+
+ float height = rect.height();
+
+ if (y < rect.top) {
+ y = 0f;
+ }
+ else if (y > rect.bottom) {
+ y = height;
+ }
+ else{
+ y = y - rect.top;
+ }
+
+ return 360f - (y * 360f / height);
+ }
+
+ private int pointToAlpha(int x) {
+
+ final RectF rect = mAlphaRect;
+ final int width = (int) rect.width();
+
+ if (x < rect.left) {
+ x = 0;
+ }
+ else if (x > rect.right) {
+ x = width;
+ }
+ else{
+ x = x - (int)rect.left;
+ }
+
+ return 0xff - (x * 0xff / width);
+
+ }
+
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+
+ float x = event.getX();
+ float y = event.getY();
+
+ boolean update = false;
+
+
+ if (event.getAction() == MotionEvent.ACTION_MOVE) {
+
+ switch(mLastTouchedPanel) {
+
+ case PANEL_SAT_VAL:
+
+ float sat, val;
+
+ sat = mSat + x/50f;
+ val = mVal - y/50f;
+
+ if (sat < 0f) {
+ sat = 0f;
+ }
+ else if (sat > 1f) {
+ sat = 1f;
+ }
+
+ if (val < 0f) {
+ val = 0f;
+ }
+ else if (val > 1f) {
+ val = 1f;
+ }
+
+ mSat = sat;
+ mVal = val;
+
+ update = true;
+
+ break;
+
+ case PANEL_HUE:
+
+ float hue = mHue - y * 10f;
+
+ if (hue < 0f) {
+ hue = 0f;
+ }
+ else if (hue > 360f) {
+ hue = 360f;
+ }
+
+ mHue = hue;
+
+ update = true;
+
+ break;
+
+ case PANEL_ALPHA:
+
+ if (!mShowAlphaPanel || mAlphaRect == null) {
+ update = false;
+ }
+ else{
+
+ int alpha = (int) (mAlpha - x*10);
+
+ if (alpha < 0) {
+ alpha = 0;
+ }
+ else if (alpha > 0xff) {
+ alpha = 0xff;
+ }
+
+ mAlpha = alpha;
+
+
+ update = true;
+ }
+
+ break;
+ }
+
+
+ }
+
+
+ if (update) {
+
+ if (mListener != null) {
+ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));
+ }
+
+ invalidate();
+ return true;
+ }
+
+
+ return super.onTrackballEvent(event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+
+ boolean update = false;
+
+ switch(event.getAction()) {
+
+ case MotionEvent.ACTION_DOWN:
+
+ mStartTouchPoint = new Point((int)event.getX(), (int)event.getY());
+
+ update = moveTrackersIfNeeded(event);
+
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+
+ update = moveTrackersIfNeeded(event);
+
+ break;
+
+ case MotionEvent.ACTION_UP:
+
+ mStartTouchPoint = null;
+
+ update = moveTrackersIfNeeded(event);
+
+ break;
+
+ }
+
+ if (update) {
+
+ if (mListener != null) {
+ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));
+ }
+
+ invalidate();
+ return true;
+ }
+
+
+ return super.onTouchEvent(event);
+ }
+
+ private boolean moveTrackersIfNeeded(MotionEvent event) {
+
+ if (mStartTouchPoint == null) return false;
+
+ boolean update = false;
+
+ int startX = mStartTouchPoint.x;
+ int startY = mStartTouchPoint.y;
+
+
+ if (mHueRect.contains(startX, startY)) {
+ mLastTouchedPanel = PANEL_HUE;
+
+ mHue = pointToHue(event.getY());
+
+ update = true;
+ }
+ else if (mSatValRect.contains(startX, startY)) {
+
+ mLastTouchedPanel = PANEL_SAT_VAL;
+
+ float[] result = pointToSatVal(event.getX(), event.getY());
+
+ mSat = result[0];
+ mVal = result[1];
+
+ update = true;
+ }
+ else if (mAlphaRect != null && mAlphaRect.contains(startX, startY)) {
+
+ mLastTouchedPanel = PANEL_ALPHA;
+
+ mAlpha = pointToAlpha((int)event.getX());
+
+ update = true;
+ }
+
+
+ return update;
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+
+ int width = 0;
+ int height = 0;
+
+ 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);
+
+
+ if (!mShowAlphaPanel) {
+ height = (int) (widthAllowed - PANEL_SPACING - HUE_PANEL_WIDTH);
+
+ //If calculated height (based on the width) is more than the allowed height.
+ if (height > heightAllowed) {
+ height = heightAllowed;
+ width = (int) (height + PANEL_SPACING + HUE_PANEL_WIDTH);
+ }
+ else{
+ width = widthAllowed;
+ }
+ }
+ else{
+
+ width = (int) (heightAllowed - ALPHA_PANEL_HEIGHT + HUE_PANEL_WIDTH);
+
+ if (width > widthAllowed) {
+ width = widthAllowed;
+ height = (int) (widthAllowed - HUE_PANEL_WIDTH + ALPHA_PANEL_HEIGHT);
+ }
+ else{
+ height = heightAllowed;
+ }
+
+
+ }
+
+
+ setMeasuredDimension(width, height);
+ }
+
+ private int chooseWidth(int mode, int size) {
+ if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
+ return size;
+ } else { // (mode == MeasureSpec.UNSPECIFIED)
+ return getPrefferedWidth();
+ }
+ }
+
+ private int chooseHeight(int mode, int size) {
+ if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
+ return size;
+ } else { // (mode == MeasureSpec.UNSPECIFIED)
+ return getPreferedHeight();
+ }
+ }
+
+ private int getPrefferedWidth() {
+
+ int width = getPreferedHeight();
+
+ if (mShowAlphaPanel) {
+ width -= (PANEL_SPACING + ALPHA_PANEL_HEIGHT);
+ }
+
+
+ return (int) (width + HUE_PANEL_WIDTH + PANEL_SPACING);
+
+ }
+
+ private int getPreferedHeight() {
+
+ int height = (int)(200 * mDensity);
+
+ if (mShowAlphaPanel) {
+ height += PANEL_SPACING + ALPHA_PANEL_HEIGHT;
+ }
+
+ return height;
+ }
+
+
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ mDrawingRect = new RectF();
+ mDrawingRect.left = mDrawingOffset + getPaddingLeft();
+ mDrawingRect.right = w - mDrawingOffset - getPaddingRight();
+ mDrawingRect.top = mDrawingOffset + getPaddingTop();
+ mDrawingRect.bottom = h - mDrawingOffset - getPaddingBottom();
+
+ setUpSatValRect();
+ setUpHueRect();
+ setUpAlphaRect();
+ }
+
+ private void setUpSatValRect() {
+
+ final RectF dRect = mDrawingRect;
+ float panelSide = dRect.height() - BORDER_WIDTH_PX * 2;
+
+ if (mShowAlphaPanel) {
+ panelSide -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
+ }
+
+ float left = dRect.left + BORDER_WIDTH_PX;
+ float top = dRect.top + BORDER_WIDTH_PX;
+ float bottom = top + panelSide;
+ float right = left + panelSide;
+
+ mSatValRect = new RectF(left,top, right, bottom);
+ }
+
+ private void setUpHueRect() {
+ final RectF dRect = mDrawingRect;
+
+ float left = dRect.right - HUE_PANEL_WIDTH + BORDER_WIDTH_PX;
+ float top = dRect.top + BORDER_WIDTH_PX;
+ float bottom = dRect.bottom - BORDER_WIDTH_PX - (mShowAlphaPanel ? (PANEL_SPACING + ALPHA_PANEL_HEIGHT) : 0);
+ float right = dRect.right - BORDER_WIDTH_PX;
+
+ mHueRect = new RectF(left, top, right, bottom);
+ }
+
+ private void setUpAlphaRect() {
+
+ if (!mShowAlphaPanel) return;
+
+ final RectF dRect = mDrawingRect;
+
+ float left = dRect.left + BORDER_WIDTH_PX;
+ float top = dRect.bottom - ALPHA_PANEL_HEIGHT + BORDER_WIDTH_PX;
+ float bottom = dRect.bottom - BORDER_WIDTH_PX;
+ float right = dRect.right - BORDER_WIDTH_PX;
+
+ mAlphaRect = new RectF(left, top, right, bottom);
+
+
+ mAlphaPattern = new AlphaPatternDrawable((int) (5 * mDensity));
+ mAlphaPattern.setBounds(Math.round(mAlphaRect.left), Math
+ .round(mAlphaRect.top), Math.round(mAlphaRect.right), Math
+ .round(mAlphaRect.bottom));
+
+
+
+ }
+
+
+ /**
+ * Set a OnColorChangedListener to get notified when the color
+ * selected by the user has changed.
+ * @param listener
+ */
+ public void setOnColorChangedListener(OnColorChangedListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Set the color of the border surrounding all panels.
+ * @param color
+ */
+ public void setBorderColor(int color) {
+ mBorderColor = color;
+ invalidate();
+ }
+
+ /**
+ * Get the color of the border surrounding all panels.
+ */
+ public int getBorderColor() {
+ return mBorderColor;
+ }
+
+ /**
+ * Get the current color this view is showing.
+ * @return the current color.
+ */
+ public int getColor() {
+ return Color.HSVToColor(mAlpha, new float[]{mHue,mSat,mVal});
+ }
+
+ /**
+ * Set the color the view should show.
+ * @param color The color that should be selected.
+ */
+ public void setColor(int color) {
+ setColor(color, false);
+ }
+
+ /**
+ * Set the color this view should show.
+ * @param color The color that should be selected.
+ * @param callback If you want to get a callback to
+ * your OnColorChangedListener.
+ */
+ public void setColor(int color, boolean callback) {
+
+ int alpha = Color.alpha(color);
+ int red = Color.red(color);
+ int blue = Color.blue(color);
+ int green = Color.green(color);
+
+ float[] hsv = new float[3];
+
+ Color.RGBToHSV(red, green, blue, hsv);
+
+ mAlpha = alpha;
+ mHue = hsv[0];
+ mSat = hsv[1];
+ mVal = hsv[2];
+
+ if (callback && mListener != null) {
+ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));
+ }
+
+ invalidate();
+ }
+
+ /**
+ * Get the drawing offset of the color picker view.
+ * The drawing offset is the distance from the side of
+ * a panel to the side of the view minus the padding.
+ * Useful if you want to have your own panel below showing
+ * the currently selected color and want to align it perfectly.
+ * @return The offset in pixels.
+ */
+ public float getDrawingOffset() {
+ return mDrawingOffset;
+ }
+
+ /**
+ * Set if the user is allowed to adjust the alpha panel. Default is false.
+ * If it is set to false no alpha will be set.
+ * @param visible
+ */
+ public void setAlphaSliderVisible(boolean visible) {
+
+ if (mShowAlphaPanel != visible) {
+ mShowAlphaPanel = visible;
+
+ /*
+ * Reset all shader to force a recreation.
+ * Otherwise they will not look right after
+ * the size of the view has changed.
+ */
+ mValShader = null;
+ mSatShader = null;
+ mHueShader = null;
+ mAlphaShader = null;;
+
+ requestLayout();
+ }
+
+ }
+
+ public void setSliderTrackerColor(int color) {
+ mSliderTrackerColor = color;
+
+ mHueTrackerPaint.setColor(mSliderTrackerColor);
+
+ invalidate();
+ }
+
+ public int getSliderTrackerColor() {
+ return mSliderTrackerColor;
+ }
+
+ /**
+ * Set the text that should be shown in the
+ * alpha slider. Set to null to disable text.
+ * @param res string resource id.
+ */
+ public void setAlphaSliderText(int res) {
+ String text = getContext().getString(res);
+ setAlphaSliderText(text);
+ }
+
+ /**
+ * Set the text that should be shown in the
+ * alpha slider. Set to null to disable text.
+ * @param text Text that should be shown.
+ */
+ public void setAlphaSliderText(String text) {
+ mAlphaSliderText = text;
+ invalidate();
+ }
+
+ /**
+ * Get the current value of the text
+ * that will be shown in the alpha
+ * slider.
+ * @return
+ */
+ public String getAlphaSliderText() {
+ return mAlphaSliderText;
+ }
+
+ /**
+ * Method that checks the support for HardwareAcceleration. Check AOSP notice<br/>
+ * <br/>
+ * <pre>
+ * 'ComposeShader can only contain shaders of different types (a BitmapShader and a
+ * LinearGradient for instance, but not two instances of BitmapShader)'. But, 'If your
+ * application is affected by any of these missing features or limitations, you can turn
+ * off hardware acceleration for just the affected portion of your application by calling
+ * setLayerType(View.LAYER_TYPE_SOFTWARE, null).'
+ */
+ private void checkHardwareAccelerationSupport() {
+ // HardwareAcceleration sit is only available since ICS. 14 = ICS_VERSION_CODE
+ if (android.os.Build.VERSION.SDK_INT >= 14) {
+ try{
+ // We need to use reflection to get that method to avoid compilation errors
+ Method isHardwareAccelerated =
+ getClass().getMethod("isHardwareAccelerated", new Class[]{});
+ Object o = isHardwareAccelerated.invoke(this, new Object[]{});
+ if (null != o && o instanceof Boolean && (Boolean)o) {
+ // HardwareAcceleration is supported. Use SoftwareAcceleration
+ Method setLayerType =
+ getClass().getMethod(
+ "setLayerType", int.class, android.graphics.Paint.class);
+ setLayerType.invoke(this, 1, new Object[]{});
+ }
+ } catch (Exception e) { /** NON BLOCK **/}
+ }
+ }
+
+}