From 8573124b80d19a9562a6e623022171b41dc4d183 Mon Sep 17 00:00:00 2001 From: Jorge Ruesga Date: Mon, 25 Mar 2013 04:56:38 +0100 Subject: 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 --- libs/android-syntax-highlight/CHANGELOG.md | 7 + libs/android-syntax-highlight/LICENSE.md | 202 +++++ libs/android-syntax-highlight/README.md | 14 + .../filemanager/ash/HighlightColors.java | 121 +++ .../ash/ISyntaxHighlightResourcesResolver.java | 55 ++ .../cyanogenmod/filemanager/ash/RegExpUtil.java | 71 ++ .../filemanager/ash/SyntaxHighlightFactory.java | 96 ++ .../filemanager/ash/SyntaxHighlightProcessor.java | 112 +++ .../filemanager/ash/scanners/NewLineScanner.java | 76 ++ .../filemanager/ash/scanners/Scanner.java | 42 + .../spi/PropertiesSyntaxHighlightProcessor.java | 281 ++++++ libs/color-picker-view/CHANGELOG.md | 4 + libs/color-picker-view/LICENSE.md | 202 +++++ libs/color-picker-view/README.md | 18 + .../drawables/AlphaPatternDrawable.java | 129 +++ .../mColorPicker/views/ColorDialogView.java | 463 ++++++++++ .../mColorPicker/views/ColorPanelView.java | 174 ++++ .../mColorPicker/views/ColorPickerView.java | 998 +++++++++++++++++++++ 18 files changed, 3065 insertions(+) create mode 100644 libs/android-syntax-highlight/CHANGELOG.md create mode 100644 libs/android-syntax-highlight/LICENSE.md create mode 100644 libs/android-syntax-highlight/README.md create mode 100644 libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java create mode 100644 libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java create mode 100644 libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java create mode 100644 libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java create mode 100644 libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java create mode 100644 libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java create mode 100644 libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java create mode 100644 libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java create mode 100644 libs/color-picker-view/CHANGELOG.md create mode 100644 libs/color-picker-view/LICENSE.md create mode 100644 libs/color-picker-view/README.md create mode 100644 libs/color-picker-view/src/afzkl/development/mColorPicker/drawables/AlphaPatternDrawable.java create mode 100644 libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorDialogView.java create mode 100644 libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPanelView.java create mode 100644 libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPickerView.java (limited to 'libs') 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 HighlightColors + * + * @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 SyntaxHighlightProcessor classes. + */ +public class SyntaxHighlightFactory { + + private static SyntaxHighlightFactory sFactory; + + private final ArrayList mProcessors; + + /** + * Constructor of SyntaxHighlightFactory + */ + public SyntaxHighlightFactory() { + super(); + this.mProcessors = new ArrayList(); + } + + /** + * 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 the list available syntax highlight processors. + */ + public List getAvailableSyntaxHighlightProcessors() { + return new ArrayList(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.
+ */ +public abstract class SyntaxHighlightProcessor { + + protected final ISyntaxHighlightResourcesResolver mResourcesResolver; + + /** + * Constructor of SyntaxHighlightProcessor + * + * @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 Spannable. + * + * @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 Scanner + * + * @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 Scanner + * + * @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 properties highlight processor class.
+ *
+ * The behaviour of this class is:
+ *
    + *
  • Comments start with # (only spaces are allowed prior to comment)
  • + *
  • Assignment character (=) separates key from value
  • + *
  • Arguments exists only in values, and are composed by {a digit}
  • + *
  • 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.
  • + *
+ *
+ * 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 PropertiesSyntaxHighlightProcessor + * + * @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 ColorDialogView + * + * @param context The current context + */ + public ColorDialogView(Context context) { + this(context, null); + } + + /** + * Constructor of ColorDialogView + * + * @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 ColorDialogView + * + * @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 EditText + */ + 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
+ *
+ *
+     * '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 **/}
+       }
+   }
+
+}
-- 
cgit v1.2.3