aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorge Ruesga <jorge@ruesga.com>2013-03-25 04:56:38 +0100
committerJorge Ruesga <jorge@ruesga.com>2013-03-27 00:16:04 +0100
commit8573124b80d19a9562a6e623022171b41dc4d183 (patch)
tree40aa0eca71ca3bd4e09abee5efa046f31cc2f308
parentd063637d6110ab2a762268d7ef20afeaa6f482af (diff)
downloadandroid_packages_apps_CMFileManager-8573124b80d19a9562a6e623022171b41dc4d183.tar.gz
android_packages_apps_CMFileManager-8573124b80d19a9562a6e623022171b41dc4d183.tar.bz2
android_packages_apps_CMFileManager-8573124b80d19a9562a6e623022171b41dc4d183.zip
CMFM: Editor initial highlight support + props syntax processor + others features
- This change enables support of syntax highlight in editor. Adds also the next syntax processors: * PropertiesSyntaxHighlightProcessor - Option for toggle "no suggestion" in editor - CleanUp Patchset 2: Theme color scheme support Patchset 3: Hexdump binary editor preference No suggestions editor preference Syntax Highlight color scheme Add android-syntax-highlight (CMFM) and color-picker-view libraries ColorPickerDialog and ColorPickerPreference Separate preference to its own file Extract themes strings from dark_theme.xml to strings.xml Rebased Change-Id: I9df65e6193d46ebafadee5d545dcde1fc5ce20e9 Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
-rw-r--r--Android.mk2
-rw-r--r--README.md3
-rw-r--r--libs/android-syntax-highlight/CHANGELOG.md7
-rw-r--r--libs/android-syntax-highlight/LICENSE.md202
-rw-r--r--libs/android-syntax-highlight/README.md14
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java121
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java55
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java71
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java96
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java112
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java76
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java42
-rw-r--r--libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java281
-rw-r--r--libs/color-picker-view/CHANGELOG.md4
-rw-r--r--libs/color-picker-view/LICENSE.md202
-rw-r--r--libs/color-picker-view/README.md18
-rw-r--r--libs/color-picker-view/src/afzkl/development/mColorPicker/drawables/AlphaPatternDrawable.java129
-rw-r--r--libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorDialogView.java463
-rw-r--r--libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPanelView.java174
-rw-r--r--libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPickerView.java998
-rw-r--r--res/layout/color_picker_pref_item.xml30
-rw-r--r--res/menu/editor.xml10
-rw-r--r--res/values/strings.xml50
-rw-r--r--res/values/theme.xml10
-rw-r--r--res/xml/preferences_editor.xml39
-rw-r--r--res/xml/preferences_editor_color_scheme.xml90
-rw-r--r--res/xml/preferences_headers.xml8
-rw-r--r--src/com/cyanogenmod/filemanager/FileManagerApplication.java2
-rw-r--r--src/com/cyanogenmod/filemanager/activities/EditorActivity.java443
-rw-r--r--src/com/cyanogenmod/filemanager/activities/PickerActivity.java8
-rw-r--r--src/com/cyanogenmod/filemanager/activities/SearchActivity.java2
-rw-r--r--src/com/cyanogenmod/filemanager/activities/preferences/EditorPreferenceFragment.java129
-rw-r--r--src/com/cyanogenmod/filemanager/activities/preferences/EditorSHColorSchemePreferenceFragment.java308
-rw-r--r--src/com/cyanogenmod/filemanager/activities/preferences/GeneralPreferenceFragment.java199
-rw-r--r--src/com/cyanogenmod/filemanager/activities/preferences/SearchPreferenceFragment.java196
-rw-r--r--src/com/cyanogenmod/filemanager/activities/preferences/SettingsPreferences.java450
-rw-r--r--src/com/cyanogenmod/filemanager/activities/preferences/ThemesPreferenceFragment.java96
-rw-r--r--src/com/cyanogenmod/filemanager/activities/preferences/TitlePreferenceFragment.java31
-rw-r--r--src/com/cyanogenmod/filemanager/preferences/FileManagerSettings.java34
-rw-r--r--src/com/cyanogenmod/filemanager/preferences/Preferences.java4
-rw-r--r--src/com/cyanogenmod/filemanager/ui/preferences/ColorPickerPreference.java253
-rw-r--r--src/com/cyanogenmod/filemanager/ui/widgets/InlineAutocompleteTextView.java2
-rw-r--r--src/com/cyanogenmod/filemanager/ui/widgets/NavigationView.java2
-rw-r--r--src/com/cyanogenmod/filemanager/util/CommandHelper.java2
-rw-r--r--src/com/cyanogenmod/filemanager/util/FileHelper.java24
-rw-r--r--themes/res/values/dark_theme.xml15
-rw-r--r--themes/res/values/strings.xml23
47 files changed, 5007 insertions, 523 deletions
diff --git a/Android.mk b/Android.mk
index ecfb4868..bbd4b66f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -19,6 +19,8 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_SRC_FILES += $(call all-java-files-under, themes/src)
+LOCAL_SRC_FILES += $(call all-java-files-under, libs/android-syntax-highlight/src)
+LOCAL_SRC_FILES += $(call all-java-files-under, libs/color-picker-view/src)
LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, themes/res res)
LOCAL_AAPT_INCLUDE_ALL_RESOURCES := true
LOCAL_AAPT_FLAGS := --auto-add-overlay
diff --git a/README.md b/README.md
index 8e1b9286..7b33f947 100644
--- a/README.md
+++ b/README.md
@@ -10,4 +10,7 @@ This source was released under the terms of
Visit [CyanogenMod Github](https://github.com/CyanogenMod) and [CyanogenMod
Code Review](http://review.cyanogenmod.com/) to get the source and patches.
+This application uses also third party libraries. Checkout the license individual
+license of every library in libs folder.
+
Copyright © 2012 The CyanogenMod Project
diff --git a/libs/android-syntax-highlight/CHANGELOG.md b/libs/android-syntax-highlight/CHANGELOG.md
new file mode 100644
index 00000000..84bfdb46
--- /dev/null
+++ b/libs/android-syntax-highlight/CHANGELOG.md
@@ -0,0 +1,7 @@
+ChangeLog
+========================
+
+Version 0.0.1
+-------------
+* Initial support
+* properties syntax highlight processor \ No newline at end of file
diff --git a/libs/android-syntax-highlight/LICENSE.md b/libs/android-syntax-highlight/LICENSE.md
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/libs/android-syntax-highlight/LICENSE.md
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/libs/android-syntax-highlight/README.md b/libs/android-syntax-highlight/README.md
new file mode 100644
index 00000000..3f7dc373
--- /dev/null
+++ b/libs/android-syntax-highlight/README.md
@@ -0,0 +1,14 @@
+Android Syntax Highlight Library
+================================
+
+A library for add syntax highlight to TextView and EditText widgets.
+
+This library was developed as part of the CMFileManager app.
+
+This source was released under the terms of
+[Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) license.
+
+Visit [CyanogenMod Github](https://github.com/CyanogenMod) and [CyanogenMod
+Code Review](http://review.cyanogenmod.com/) to get the source and patches.
+
+Copyright © 2013 The CyanogenMod Project
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java
new file mode 100644
index 00000000..5e31dab7
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.filemanager.ash;
+
+import android.graphics.Color;
+
+/**
+ * An enumeration of all the color resources available for syntax highlight processors.
+ */
+public enum HighlightColors {
+
+ /**
+ * Text color
+ */
+ TEXT(
+ "ash_text", //$NON-NLS-1$
+ "ash_text_color", //$NON-NLS-1$
+ Color.argb(153, 0, 0, 0)),
+ /**
+ * Assignment text color
+ */
+ ASSIGNMENT(
+ "ash_assignment", //$NON-NLS-1$
+ "ash_assignment_color", //$NON-NLS-1$
+ Color.argb(153, 0, 0, 0)),
+ /**
+ * Single line comment color
+ */
+ SINGLE_LINE_COMMENT(
+ "ash_singleline_comment", //$NON-NLS-1$
+ "ash_singleline_comment_color", //$NON-NLS-1$
+ Color.argb(255, 63, 127, 95)),
+ /**
+ * Multiline line comment color
+ */
+ MULTILINE_LINE_COMMENT(
+ "ash_multiline_comment", //$NON-NLS-1$
+ "ash_multiline_comment_color", //$NON-NLS-1$
+ Color.argb(255, 127, 159, 191)),
+ /**
+ * Keyword color
+ */
+ KEYWORD(
+ "ash_keyword", //$NON-NLS-1$
+ "ash_keyword_color", //$NON-NLS-1$
+ Color.argb(255, 127, 0, 85)),
+ /**
+ * Quoted string color
+ */
+ QUOTED_STRING(
+ "ash_quoted_string", //$NON-NLS-1$
+ "ash_quoted_string_color", //$NON-NLS-1$
+ Color.argb(255, 42, 0, 255)),
+ /**
+ * Variable color
+ */
+ VARIABLE(
+ "ash_variable", //$NON-NLS-1$
+ "ash_variable_color", //$NON-NLS-1$
+ Color.argb(153, 0, 0, 192));
+
+
+ private final String mId;
+ private final String mResId;
+ private final int mDefault;
+
+ /**
+ * Constructor of <code>HighlightColors</code>
+ *
+ * @param id The id of the object
+ * @param resid The resource id
+ * @param def The default value
+ */
+ HighlightColors(String id, String resid, int def) {
+ this.mId = id;
+ this.mResId = resid;
+ this.mDefault = def;
+ }
+
+ /**
+ * Returns the identifier
+ *
+ * @return String The identifier
+ */
+ public String getId() {
+ return this.mId;
+ }
+
+ /**
+ * Returns the resource identifier
+ *
+ * @return String The resource identifier
+ */
+ public String getResId() {
+ return this.mResId;
+ }
+
+ /**
+ * Returns the default value
+ *
+ * @return String The default value
+ */
+ public int getDefault() {
+ return this.mDefault;
+ }
+
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java
new file mode 100644
index 00000000..11170e7c
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.filemanager.ash;
+
+/**
+ * An interface that should be implemented by the library caller, to
+ * resolve resources needed by the syntax processors.
+ *
+ * @see HighlightColors
+ */
+public interface ISyntaxHighlightResourcesResolver {
+
+ /**
+ * Method that returns a string
+ *
+ * @param id The color unique id
+ * @param resid The resource identifier
+ * @return CharSequence The string
+ */
+ CharSequence getString(String id, String resid);
+
+ /**
+ * Method that returns an integer
+ *
+ * @param id The color unique id
+ * @param resid The resource identifier
+ * @param def The default value
+ * @return int The integer value
+ */
+ int getInteger(String id, String resid, int def);
+
+ /**
+ * Method that returns a color
+ *
+ * @param id The color unique id
+ * @param resid The resource identifier
+ * @param def The default value
+ * @return int The color
+ */
+ int getColor(String id, String resid, int def);
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java
new file mode 100644
index 00000000..283eba90
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.filemanager.ash;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * A helper class for deal with patters
+ */
+public final class RegExpUtil {
+
+ /**
+ * A constant that is returned when the no expression matches.
+ */
+ public static final int NO_MATCH = -1;
+
+ /**
+ * New line pattern
+ */
+ public static final Pattern NEWLINE_PATTERN = Pattern.compile("(\r\n|\n|\r)"); //$NON-NLS-1$
+
+ /**
+ * Method that returns the last match position of a regexp,
+ *
+ * @param pattern The patter
+ * @param input The input
+ * @param withPattern Whether the return position should contains the pattern or not.
+ * @return int The matched position or -1
+ */
+ public static int getLastMatch(Pattern pattern, CharSequence input, boolean withPattern) {
+ Matcher m = pattern.matcher(input);
+ int p = NO_MATCH;
+ while (m.find()) {
+ p = withPattern ? m.start() : m.end();
+ }
+ return p;
+ }
+
+ /**
+ * Method that returns the next match position of a regexp,
+ *
+ * @param pattern The patter
+ * @param input The input
+ * @param withPattern Whether the return position should contains the pattern or not.
+ * @return int The matched position or -1
+ */
+ public static int getNextMatch(Pattern pattern, CharSequence input, boolean withPattern) {
+ Matcher m = pattern.matcher(input);
+ int p = NO_MATCH;
+ if (m.find()) {
+ return withPattern ? m.end() : m.start();
+ }
+ return p;
+ }
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java
new file mode 100644
index 00000000..20c85dc2
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.filemanager.ash;
+
+import com.cyanogenmod.filemanager.ash.spi.PropertiesSyntaxHighlightProcessor;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A factory of <code>SyntaxHighlightProcessor</code> classes.
+ */
+public class SyntaxHighlightFactory {
+
+ private static SyntaxHighlightFactory sFactory;
+
+ private final ArrayList<SyntaxHighlightProcessor> mProcessors;
+
+ /**
+ * Constructor of <code>SyntaxHighlightFactory</code>
+ */
+ public SyntaxHighlightFactory() {
+ super();
+ this.mProcessors = new ArrayList<SyntaxHighlightProcessor>();
+ }
+
+ /**
+ * Method that returns the default highlight factory instance
+ *
+ * @param resolver A class for allow the processor to obtain resources
+ * @return SyntaxHighlightFactory The default syntax highlight factory
+ */
+ public static final synchronized SyntaxHighlightFactory getDefaultFactory(
+ ISyntaxHighlightResourcesResolver resolver) {
+ if (sFactory == null) {
+ sFactory = createDefaultFactory(resolver);
+ }
+ return sFactory;
+ }
+
+ /**
+ * Method that returns the syntax highlight processor that can handle the file
+ *
+ * @param file The file to process
+ * @return SyntaxHighlightProcessor The syntax highlight processor
+ */
+ public SyntaxHighlightProcessor getSyntaxHighlightProcessor(File file) {
+ int cc = this.mProcessors.size();
+ for (int i = 0; i < cc; i++) {
+ SyntaxHighlightProcessor processor = this.mProcessors.get(i);
+ if (processor.accept(file)) {
+ return processor;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Method that return all the available syntax highlight processors.
+ *
+ * @return List<SyntaxHighlightProcessor> the list available syntax highlight processors.
+ */
+ public List<SyntaxHighlightProcessor> getAvailableSyntaxHighlightProcessors() {
+ return new ArrayList<SyntaxHighlightProcessor>(this.mProcessors);
+ }
+
+ /**
+ * Method that create the default syntax highlight factory.
+ *
+ * @param resolver A class for allow the processor to obtain resources
+ * @return SyntaxHighlightFactory The default factory
+ */
+ private static SyntaxHighlightFactory createDefaultFactory(
+ ISyntaxHighlightResourcesResolver resolver) {
+ // TODO Read all processors classes of the SPI package
+ // For now we add all known syntax highlight processors
+ SyntaxHighlightFactory factory = new SyntaxHighlightFactory();
+ factory.mProcessors.add(new PropertiesSyntaxHighlightProcessor(resolver));
+ return factory;
+ }
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java
new file mode 100644
index 00000000..2d520346
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.filemanager.ash;
+
+import android.text.Spannable;
+import android.text.Spanned;
+import android.text.style.ForegroundColorSpan;
+
+import java.io.File;
+
+/**
+ * The base class for all the syntax highlight processors.</br>
+ */
+public abstract class SyntaxHighlightProcessor {
+
+ protected final ISyntaxHighlightResourcesResolver mResourcesResolver;
+
+ /**
+ * Constructor of <code>SyntaxHighlightProcessor</code>
+ *
+ * @param resolver A class for resolve resources
+ */
+ public SyntaxHighlightProcessor(ISyntaxHighlightResourcesResolver resolver) {
+ super();
+ this.mResourcesResolver = resolver;
+ }
+
+ /**
+ * Method that request to the syntax highlight processor if it is able to parse
+ * the file
+ *
+ * @param file The file to check
+ * @return boolean If the syntax highlight processor accepts process the file
+ */
+ protected abstract boolean accept(File file);
+
+ /**
+ * Method that initializes the processor
+ */
+ public abstract void initialize();
+
+ /**
+ * Method that request to the syntax highlight processor to do process and highlight a
+ * document. This method request a full process.
+ *
+ * @param spanable The spannable source to highlight
+ */
+ public abstract void process(Spannable spanable);
+
+ /**
+ * Method that request to the syntax highlight processor to process and highlight a
+ * document. This method request a partial process.
+ *
+ * @param spanable The spannable source to highlight
+ * @param start The start of spannable to process
+ * @param end The end of spannable to process
+ */
+ public abstract void process(Spannable spanable, int start, int end);
+
+ /**
+ * Method that cancels the active processor
+ */
+ public abstract void cancel();
+
+ /**
+ * Method that clear all the existent spans
+ *
+ * @param spanable The spannable
+ */
+ @SuppressWarnings("static-method")
+ public void clear(Spannable spanable) {
+ ForegroundColorSpan[] spans =
+ spanable.getSpans(0, spanable.length(), ForegroundColorSpan.class);
+ int cc = spans.length;
+ for (int i = 0; i < cc; i++) {
+ spanable.removeSpan(spans[i]);
+ }
+ }
+
+
+ /**
+ * Method that sets a new <code>Spannable</code>.
+ *
+ * @param spanable The spannable
+ * @param color The color of the span
+ * @param start The start of the span
+ * @param end The end of the span
+ */
+ @SuppressWarnings("static-method")
+ protected void setSpan(Spannable spanable, int color, int start, int end) {
+ if (start == end) return;
+ spanable.setSpan(
+ new ForegroundColorSpan(color),
+ start,
+ end,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java
new file mode 100644
index 00000000..5552b8eb
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.filemanager.ash.scanners;
+
+import java.util.regex.Matcher;
+
+import com.cyanogenmod.filemanager.ash.RegExpUtil;
+
+/**
+ * An scanner to process an input, reporting every text into new lines.
+ */
+public class NewLineScanner extends Scanner {
+
+ private final NewLineScannerListener mListener;
+
+ /**
+ * The listener for the newline scanner
+ */
+ public interface NewLineScannerListener {
+ /**
+ * When a new line is ready
+ *
+ * @param newline The newline detected
+ * @param start The start position of the new line within the input text
+ * @param end The end position of the new line within the input text
+ * @param sep The line separator detected
+ * @return boolean If processor must continue with the next line
+ */
+ boolean onNewLine(CharSequence newline, int start, int end, CharSequence sep);
+ }
+
+ /**
+ * Constructor of <code>Scanner</code>
+ *
+ * @param input The input
+ * @param listener The listener where return every new line
+ */
+ public NewLineScanner(CharSequence input, NewLineScannerListener listener) {
+ super(input);
+ this.mListener = listener;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void scan() {
+ if (this.mInput.length() == 0) return;
+ Matcher m = RegExpUtil.NEWLINE_PATTERN.matcher(this.mInput);
+ int next = 0;
+ while(m.find(next)) {
+ CharSequence line = this.mInput.subSequence(next, m.start());
+ if (!this.mListener.onNewLine(line, next, m.start(), m.group())) {
+ return;
+ }
+ next = m.end();
+ }
+ // The non-matched data
+ CharSequence line = this.mInput.subSequence(next, this.mInput.length());
+ this.mListener.onNewLine(line, next, this.mInput.length(), null);
+ }
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java
new file mode 100644
index 00000000..31583456
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.cyanogenmod.filemanager.ash.scanners;
+
+
+/**
+ * The base class for all the scanners
+ */
+public abstract class Scanner {
+
+ CharSequence mInput;
+
+ /**
+ * Constructor of <code>Scanner</code>
+ *
+ * @param input The input
+ */
+ public Scanner(CharSequence input) {
+ super();
+ this.mInput = input;
+ }
+
+ /**
+ * Method that starts the scan process
+ */
+ public abstract void scan();
+}
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java
new file mode 100644
index 00000000..f9fd19a2
--- /dev/null
+++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.filemanager.ash.spi;
+
+import android.text.Spannable;
+import android.text.style.ForegroundColorSpan;
+
+import com.cyanogenmod.filemanager.ash.HighlightColors;
+import com.cyanogenmod.filemanager.ash.ISyntaxHighlightResourcesResolver;
+import com.cyanogenmod.filemanager.ash.RegExpUtil;
+import com.cyanogenmod.filemanager.ash.SyntaxHighlightProcessor;
+import com.cyanogenmod.filemanager.ash.scanners.NewLineScanner;
+import com.cyanogenmod.filemanager.ash.scanners.NewLineScanner.NewLineScannerListener;
+
+import java.io.File;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A <b>properties</b> highlight processor class.</br>
+ * </br>
+ * The behaviour of this class is:</br>
+ * <ul>
+ * <li>Comments start with # (only spaces are allowed prior to comment)</li>
+ * <li>Assignment character (=) separates key from value</li>
+ * <li>Arguments exists only in values, and are composed by {a digit}</li>
+ * <li>Values can be extended in multiple lines if line ends with the char "\". A
+ * comment in multiline breaks the multiline and starts a new property.</li>
+ * </ul>
+ * </br>
+ * IMP! This class is not thread safe. Calling "process" methods should be
+ * done in a synchronous way.
+ */
+public class PropertiesSyntaxHighlightProcessor extends SyntaxHighlightProcessor {
+
+ private static final String EXT_PROP = "prop"; //$NON-NLS-1$
+ private static final String EXT_PROPERTIES = "properties"; //$NON-NLS-1$
+
+ private static final Pattern COMMENT = Pattern.compile("^\\s*#.*"); //$NON-NLS-1$
+ private static final Pattern MULTILINE = Pattern.compile(".*\\\\\\s*$"); //$NON-NLS-1$
+ private static final Pattern ASSIGNMENT = Pattern.compile("="); //$NON-NLS-1$
+ private static final Pattern ARGUMENT = Pattern.compile("\\{\\d+\\}"); //$NON-NLS-1$
+
+ protected Spannable mSpannable;
+ private boolean mMultiLine;
+
+ private int mKeyColor;
+ private int mAssignmentColor;
+ private int mCommentColor;
+ private int mValueColor;
+ private int mArgumentColor;
+
+ /**
+ * Constructor of <code>PropertiesSyntaxHighlightProcessor</code>
+ *
+ * @param resolver A class for resolve resources
+ */
+ public PropertiesSyntaxHighlightProcessor(ISyntaxHighlightResourcesResolver resolver) {
+ super(resolver);
+ initialize();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean accept(File file) {
+ if (file == null) return false;
+ return file.getName().toLowerCase().endsWith(EXT_PROP) ||
+ file.getName().toLowerCase().endsWith(EXT_PROPERTIES);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void initialize() {
+ this.mMultiLine = false;
+ this.mSpannable = null;
+ if (this.mResourcesResolver != null) {
+ this.mKeyColor = this.mResourcesResolver.getColor(
+ HighlightColors.TEXT.getId(),
+ HighlightColors.TEXT.getResId(),
+ HighlightColors.TEXT.getDefault());
+ this.mAssignmentColor = this.mResourcesResolver.getColor(
+ HighlightColors.ASSIGNMENT.getId(),
+ HighlightColors.ASSIGNMENT.getResId(),
+ HighlightColors.ASSIGNMENT.getDefault());
+ this.mCommentColor = this.mResourcesResolver.getColor(
+ HighlightColors.SINGLE_LINE_COMMENT.getId(),
+ HighlightColors.SINGLE_LINE_COMMENT.getResId(),
+ HighlightColors.SINGLE_LINE_COMMENT.getDefault());
+ this.mValueColor = this.mResourcesResolver.getColor(
+ HighlightColors.VARIABLE.getId(),
+ HighlightColors.VARIABLE.getResId(),
+ HighlightColors.VARIABLE.getDefault());
+ this.mArgumentColor = this.mResourcesResolver.getColor(
+ HighlightColors.KEYWORD.getId(),
+ HighlightColors.KEYWORD.getResId(),
+ HighlightColors.KEYWORD.getDefault());
+ } else {
+ // By default
+ this.mKeyColor = HighlightColors.TEXT.getDefault();
+ this.mAssignmentColor = HighlightColors.TEXT.getDefault();
+ this.mCommentColor = HighlightColors.SINGLE_LINE_COMMENT.getDefault();
+ this.mValueColor = HighlightColors.VARIABLE.getDefault();
+ this.mArgumentColor = HighlightColors.KEYWORD.getDefault();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void process(final Spannable spanable) {
+ this.mMultiLine = false;
+ this.mSpannable = spanable;
+ clear(spanable);
+ NewLineScanner scanner = new NewLineScanner(spanable, new NewLineScannerListener() {
+ @Override
+ public boolean onNewLine(CharSequence newline, int start, int end, CharSequence sep) {
+ processNewLine(newline, start, end);
+ return true;
+ }
+
+ });
+ scanner.scan();
+ this.mSpannable = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void process(final Spannable spanable, final int start, final int end) {
+ // We need a Retrieve the previous line
+ this.mMultiLine = false;
+ this.mSpannable = spanable;
+ CharSequence seqs = spanable.subSequence(0, start);
+ CharSequence seqe = spanable.subSequence(end, spanable.length());
+ int s1 = RegExpUtil.getLastMatch(RegExpUtil.NEWLINE_PATTERN, seqs, false);
+ if (s1 == RegExpUtil.NO_MATCH) {
+ s1 = 0;
+ }
+ int e1 = RegExpUtil.getNextMatch(RegExpUtil.NEWLINE_PATTERN, seqe, false);
+ if (e1 == RegExpUtil.NO_MATCH) {
+ e1 = spanable.length();
+ } else {
+ e1 += end;
+ }
+
+ // Also, we need to know about if the previous line is multiline
+ if (s1 > 0) {
+ int s2 = RegExpUtil.getLastMatch(RegExpUtil.NEWLINE_PATTERN, seqs, true);
+ CharSequence seqnl = spanable.subSequence(0, s2);
+ int snl = RegExpUtil.getLastMatch(RegExpUtil.NEWLINE_PATTERN, seqnl, false);
+ Matcher mlm = MULTILINE.matcher(
+ spanable.subSequence(snl != RegExpUtil.NO_MATCH ? snl : 0, s2));
+ this.mMultiLine = mlm.matches();
+ }
+
+ // Process the new line
+ if (s1 != e1) {
+ processNewLine(spanable.subSequence(s1, e1), s1, e1);
+ }
+
+ // Now, multiline again (next line). We check always the next line, because we
+ // don't know if user delete multiline flag in the current line
+ e1 = RegExpUtil.getNextMatch(RegExpUtil.NEWLINE_PATTERN, seqe, true);
+ if (e1 != RegExpUtil.NO_MATCH) {
+ e1 += end;
+ seqe = spanable.subSequence(e1, spanable.length());
+ int e2 = RegExpUtil.getNextMatch(RegExpUtil.NEWLINE_PATTERN, seqe, false);
+ if (e2 == RegExpUtil.NO_MATCH) {
+ e2 = spanable.length();
+ } else {
+ e2 += e1;
+ }
+ processNewLine(spanable.subSequence(e1, e2), e1, e2);
+ }
+
+ this.mSpannable = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void cancel() {
+ // Not needed by this processor
+ }
+
+ /**
+ * A method to process every new line
+ *
+ * @param newline The newline
+ * @param start The start position of the line
+ * @param end The end position of the line
+ * @hide
+ */
+ void processNewLine(CharSequence newline, int start, int end) {
+ // Remove all spannable of the line (this processor doesn't multiline spans and
+ // only uses ForegroundColorSpan spans)
+ ForegroundColorSpan[] spans =
+ this.mSpannable.getSpans(start, end, ForegroundColorSpan.class);
+ int cc = spans.length;
+ for (int i = 0; i < cc; i++) {
+ this.mSpannable.removeSpan(spans[i]);
+ }
+
+ // Find comment
+ Matcher cm = COMMENT.matcher(newline);
+ if (cm.matches()) {
+ // All the line is a comment
+ setSpan(this.mSpannable, this.mCommentColor, start, end);
+ this.mMultiLine = false;
+ return;
+ }
+
+ // Has multiline
+ Matcher mlm = MULTILINE.matcher(newline);
+ boolean ml = mlm.matches();
+
+ //Find the assignment
+ int k = this.mMultiLine ? -1 : start;
+ int v = start;
+ int v2 = 0;
+ int a = -1;
+ if (!this.mMultiLine) {
+ Matcher am = ASSIGNMENT.matcher(newline);
+ if (am.find()) {
+ // Assignment found
+ v2 = am.start() + 1;
+ a = start + am.start();
+ v = a + 1;
+ }
+ }
+
+ // All the string is a key
+ if (!this.mMultiLine && a == -1) {
+ setSpan(this.mSpannable, this.mKeyColor, start, end);
+
+ } else {
+ // Key
+ if (!this.mMultiLine) {
+ setSpan(this.mSpannable, this.mKeyColor, k, a);
+ }
+ // Assignment
+ if (!this.mMultiLine) {
+ setSpan(this.mSpannable, this.mAssignmentColor, a, a + 1);
+ }
+ // Value
+ setSpan(this.mSpannable, this.mValueColor, v, end);
+ // Argument
+ Matcher argm = ARGUMENT.matcher(newline);
+ while (argm.find(v2)) {
+ int s = start + argm.start();
+ int e = start + argm.end();
+ setSpan(this.mSpannable, this.mArgumentColor, s, e);
+ v2 = argm.end();
+ }
+ }
+
+ // Multiline?
+ this.mMultiLine = ml;
+ }
+}
diff --git a/libs/color-picker-view/CHANGELOG.md b/libs/color-picker-view/CHANGELOG.md
new file mode 100644
index 00000000..342ba60e
--- /dev/null
+++ b/libs/color-picker-view/CHANGELOG.md
@@ -0,0 +1,4 @@
+ChangeLog
+========================
+
+The source was grabbed from version 1.0 (r8)
diff --git a/libs/color-picker-view/LICENSE.md b/libs/color-picker-view/LICENSE.md
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/libs/color-picker-view/LICENSE.md
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/libs/color-picker-view/README.md b/libs/color-picker-view/README.md
new file mode 100644
index 00000000..b26ef5aa
--- /dev/null
+++ b/libs/color-picker-view/README.md
@@ -0,0 +1,18 @@
+mColorPicker
+================================
+
+A color picker is something that has always been missing from the standard
+set of components which developers can build their user interface in Android
+with. Although there have been a few color pickers floating around on the
+internet I never found any that I thought was good enough for use in my
+applications so I sat down to write my own. This is the result and I have
+decided to release it as open source application for all you developers
+out there to use, free of charge of course.
+
+Checkout latest sources at http://code.google.com/p/color-picker-view/
+
+This library is released under the [Apache 2.0]
+http://www.apache.org/licenses/LICENSE-2.0.html) license.
+
+Copyright © 2010 Daniel Nilsson
+Copyright © 2013 The CyanogenMod Project
diff --git a/libs/color-picker-view/src/afzkl/development/mColorPicker/drawables/AlphaPatternDrawable.java b/libs/color-picker-view/src/afzkl/development/mColorPicker/drawables/AlphaPatternDrawable.java
new file mode 100644
index 00000000..e878756d
--- /dev/null
+++ b/libs/color-picker-view/src/afzkl/development/mColorPicker/drawables/AlphaPatternDrawable.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 Daniel Nilsson
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package afzkl.development.mColorPicker.drawables;
+
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+/**
+ * This drawable that draws a simple white and gray chessboard pattern.
+ * It's pattern you will often see as a background behind a
+ * partly transparent image in many applications.
+ * @author Daniel Nilsson
+ */
+@SuppressWarnings("all")
+public class AlphaPatternDrawable extends Drawable {
+
+ private int mRectangleSize = 10;
+
+ private final Paint mPaint = new Paint();
+ private final Paint mPaintWhite = new Paint();
+ private final Paint mPaintGray = new Paint();
+
+ private int numRectanglesHorizontal;
+ private int numRectanglesVertical;
+
+ /**
+ * Bitmap in which the pattern will be cahched.
+ */
+ private Bitmap mBitmap;
+
+ public AlphaPatternDrawable(int rectangleSize) {
+ mRectangleSize = rectangleSize;
+ mPaintWhite.setColor(0xffffffff);
+ mPaintGray.setColor(0xffcbcbcb);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.drawBitmap(mBitmap, null, getBounds(), mPaint);
+ }
+
+ @Override
+ public int getOpacity() {
+ return 0;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ throw new UnsupportedOperationException("Alpha is not supported by this drawwable.");
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ throw new UnsupportedOperationException("ColorFilter is not supported by this drawwable.");
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ super.onBoundsChange(bounds);
+
+ int height = bounds.height();
+ int width = bounds.width();
+
+ numRectanglesHorizontal = (int) Math.ceil((width / mRectangleSize));
+ numRectanglesVertical = (int) Math.ceil(height / mRectangleSize);
+
+ generatePatternBitmap();
+
+ }
+
+ /**
+ * This will generate a bitmap with the pattern
+ * as big as the rectangle we were allow to draw on.
+ * We do this to chache the bitmap so we don't need to
+ * recreate it each time draw() is called since it
+ * takes a few milliseconds.
+ */
+ private void generatePatternBitmap() {
+
+ if (getBounds().width() <= 0 || getBounds().height() <= 0) {
+ return;
+ }
+
+ mBitmap = Bitmap.createBitmap(getBounds().width(), getBounds().height(), Config.ARGB_8888);
+ Canvas canvas = new Canvas(mBitmap);
+
+ Rect r = new Rect();
+ boolean verticalStartWhite = true;
+ for (int i = 0; i <= numRectanglesVertical; i++) {
+
+ boolean isWhite = verticalStartWhite;
+ for (int j = 0; j <= numRectanglesHorizontal; j++) {
+
+ r.top = i * mRectangleSize;
+ r.left = j * mRectangleSize;
+ r.bottom = r.top + mRectangleSize;
+ r.right = r.left + mRectangleSize;
+
+ canvas.drawRect(r, isWhite ? mPaintWhite : mPaintGray);
+
+ isWhite = !isWhite;
+ }
+
+ verticalStartWhite = !verticalStartWhite;
+
+ }
+
+ }
+
+}
diff --git a/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorDialogView.java b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorDialogView.java
new file mode 100644
index 00000000..d35becf2
--- /dev/null
+++ b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorDialogView.java
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2013 Jorge Ruesga
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package afzkl.development.mColorPicker.views;
+
+import afzkl.development.mColorPicker.views.ColorPickerView.OnColorChangedListener;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.InputType;
+import android.text.Spanned;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+/**
+ * A view use directly into a dialog. It contains a one {@link ColorPickerView}
+ * and two {@link ColorPanelView} (the current color and the new color)
+ */
+public class ColorDialogView extends RelativeLayout
+ implements OnColorChangedListener, TextWatcher {
+
+ private static final int DEFAULT_MARGIN_DP = 16;
+ private static final int DEFAULT_PANEL_HEIGHT_DP = 32;
+ private static final int DEFAULT_TEXT_SIZE_SP = 12;
+ private static final int DEFAULT_LABEL_TEXT_SIZE_SP = 18;
+
+ private ColorPickerView mPickerView;
+ private ColorPanelView mCurrentColorView;
+ private ColorPanelView mNewColorView;
+ private TextView tvCurrent;
+ private TextView tvNew;
+ private TextView tvColorLabel;
+ private EditText etColor;
+
+ private String mCurrentLabelText = "Current:"; //$NON-NLS-1$
+ private String mNewLabelText = "New:"; //$NON-NLS-1$
+
+ private String mColorLabelText = "Color:"; //$NON-NLS-1$
+
+ /**
+ * Constructor of <code>ColorDialogView</code>
+ *
+ * @param context The current context
+ */
+ public ColorDialogView(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Constructor of <code>ColorDialogView</code>
+ *
+ * @param context The current context
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ */
+ public ColorDialogView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ /**
+ * Constructor of <code>ColorDialogView</code>
+ *
+ * @param context The current context
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ * @param defStyle The default style to apply to this view. If 0, no style
+ * will be applied (beyond what is included in the theme). This may
+ * either be an attribute resource, whose value will be retrieved
+ * from the current theme, or an explicit style resource.
+ */
+ public ColorDialogView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ /**
+ * Method that initializes the view. This method loads all the necessary
+ * information and create an appropriate layout for the view
+ */
+ private void init() {
+ // To fight color branding.
+ ((Activity)getContext()).getWindow().setFormat(PixelFormat.RGBA_8888);
+
+ // Creates the color input field
+ int id = createColorInput();
+
+ // Creates the color picker
+ id = createColorPicker(id);
+
+ // Creates the current color and new color panels
+ id = createColorsPanel(id);
+
+ // Sets the input color
+ this.etColor.setText(toHex(this.mNewColorView.getColor()));
+ }
+
+ /**
+ * Method that creates the color input
+ */
+ private int createColorInput() {
+ final int dlgMarging = (int)convertDpToPixel(DEFAULT_MARGIN_DP);
+ LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT);
+ lp2.setMargins(0, 0, dlgMarging, 0);
+ this.tvColorLabel = new TextView(getContext());
+ this.tvColorLabel.setText(this.mColorLabelText);
+ this.tvColorLabel.setTextSize(TypedValue.COMPLEX_UNIT_SP, DEFAULT_LABEL_TEXT_SIZE_SP);
+ this.tvColorLabel.setGravity(Gravity.BOTTOM | Gravity.LEFT);
+ this.tvColorLabel.setLayoutParams(lp2);
+
+ lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
+ this.etColor = new EditText(getContext());
+ this.etColor.setSingleLine();
+ this.etColor.setGravity(Gravity.TOP | Gravity.LEFT);
+ this.etColor.setCursorVisible(true);
+ this.etColor.setImeOptions(
+ EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_FULLSCREEN);
+ this.etColor.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+ this.etColor.setLayoutParams(lp2);
+ InputFilter[] filters = new InputFilter[2];
+ filters[0] = new InputFilter.LengthFilter(8);
+ filters[1] = new InputFilter() {
+ @Override
+ public CharSequence filter(CharSequence source, int start,
+ int end, Spanned dest, int dstart, int dend) {
+ if (start >= end) return ""; //$NON-NLS-1$
+ String s = source.subSequence(start, end).toString();
+ StringBuilder sb = new StringBuilder();
+ int cc = s.length();
+ for (int i = 0; i < cc; i++) {
+ char c = s.charAt(i);
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F')) {
+ sb.append(c);
+ }
+ }
+ return sb.toString().toUpperCase();
+ }
+ };
+ this.etColor.setFilters(filters);
+ this.etColor.addTextChangedListener(this);
+
+ LinearLayout ll1 = new LinearLayout(getContext());
+ ll1.setId(generateViewId());
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
+ lp.setMargins(dlgMarging, 0, dlgMarging, 0);
+ lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ ll1.setLayoutParams(lp);
+ ll1.addView(this.tvColorLabel);
+ ll1.addView(this.etColor);
+ addView(ll1);
+
+ return ll1.getId();
+ }
+
+ /**
+ * Method that creates the color picker
+ *
+ * @param belowOf The anchor view
+ * @return id The layout id
+ */
+ private int createColorPicker(int belowOf) {
+ final int dlgMarging = (int)convertDpToPixel(DEFAULT_MARGIN_DP);
+ this.mPickerView = new ColorPickerView(getContext());
+ this.mPickerView.setId(generateViewId());
+ this.mPickerView.setOnColorChangedListener(this);
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
+ lp.setMargins(dlgMarging, 0, dlgMarging, 0);
+ lp.addRule(RelativeLayout.BELOW, belowOf);
+ this.mPickerView.setLayoutParams(lp);
+ addView(this.mPickerView);
+ return this.mPickerView.getId();
+ }
+
+ /**
+ * Method that creates the colors panel (current and new)
+ *
+ * @param belowOf The anchor view
+ * @return id The layout id
+ */
+ private int createColorsPanel(int belowOf) {
+ final int dlgMarging = (int)convertDpToPixel(DEFAULT_MARGIN_DP);
+ final int panelHeight = (int)convertDpToPixel(DEFAULT_PANEL_HEIGHT_DP);
+ LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ 1);
+
+ // Titles
+ this.tvCurrent = new TextView(getContext());
+ lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ 1);
+ this.tvCurrent.setLayoutParams(lp2);
+ this.tvCurrent.setText(this.mCurrentLabelText);
+ this.tvCurrent.setTextSize(TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE_SP);
+ this.tvNew = new TextView(getContext());
+ this.tvNew.setLayoutParams(lp2);
+ this.tvNew.setText(this.mNewLabelText);
+ this.tvNew.setTextSize(TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE_SP);
+ TextView sep1 = new TextView(getContext());
+ lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ 0);
+ lp2.setMargins(dlgMarging, 0, dlgMarging, 0);
+ sep1.setLayoutParams(lp2);
+ sep1.setText(" "); //$NON-NLS-1$
+ sep1.setTextSize(TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE_SP);
+
+ LinearLayout ll1 = new LinearLayout(getContext());
+ ll1.setId(generateViewId());
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
+ lp.setMargins(dlgMarging, 0, dlgMarging, dlgMarging/2);
+ lp.addRule(RelativeLayout.BELOW, belowOf);
+ ll1.setLayoutParams(lp);
+ ll1.addView(this.tvCurrent);
+ ll1.addView(sep1);
+ ll1.addView(this.tvNew);
+ addView(ll1);
+
+ // Color panels
+ lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ 1);
+ this.mCurrentColorView = new ColorPanelView(getContext());
+ this.mCurrentColorView.setLayoutParams(lp2);
+ this.mNewColorView = new ColorPanelView(getContext());
+ this.mNewColorView.setLayoutParams(lp2);
+ TextView sep2 = new TextView(getContext());
+ lp2 = new LinearLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
+ 0);
+ lp2.setMargins(dlgMarging, 0, dlgMarging, 0);
+ sep2.setLayoutParams(lp2);
+ sep2.setText("-"); //$NON-NLS-1$
+ sep2.setTextSize(TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE_SP);
+
+ LinearLayout ll2 = new LinearLayout(getContext());
+ ll2.setId(generateViewId());
+ lp = new RelativeLayout.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT, panelHeight);
+ lp.setMargins(dlgMarging, 0, dlgMarging, dlgMarging/2);
+ lp.addRule(RelativeLayout.BELOW, ll1.getId());
+ ll2.setLayoutParams(lp);
+ ll2.addView(this.mCurrentColorView);
+ ll2.addView(sep2);
+ ll2.addView(this.mNewColorView);
+ addView(ll2);
+
+ return ll2.getId();
+ }
+
+ /**
+ * Method that returns the color of the picker
+ *
+ * @return The ARGB color
+ */
+ public int getColor() {
+ return this.mPickerView.getColor();
+ }
+
+ /**
+ * Method that set the color of the picker
+ *
+ * @param argb The ARGB color
+ */
+ public void setColor(int argb) {
+ setColor(argb, false);
+ }
+
+ /**
+ * Method that set the color of the picker
+ *
+ * @param argb The ARGB color
+ * @param fromEditText If the call comes from the <code>EditText</code>
+ */
+ private void setColor(int argb, boolean fromEditText) {
+ this.mPickerView.setColor(argb, false);
+ this.mCurrentColorView.setColor(argb);
+ this.mNewColorView.setColor(argb);
+ if (!fromEditText) {
+ this.etColor.setText(toHex(this.mNewColorView.getColor()));
+ }
+ }
+
+ /**
+ * Method that display/hide the alpha slider
+ *
+ * @param show If the alpha slider should be shown
+ */
+ public void showAlphaSlider(boolean show) {
+ this.mPickerView.setAlphaSliderVisible(show);
+ }
+
+ /**
+ * Set the text that should be shown in the alpha slider.
+ * Set to null to disable text.
+ *
+ * @param text Text that should be shown.
+ */
+ public void setAlphaSliderText(String text) {
+ this.mPickerView.setAlphaSliderText(text);
+ }
+
+ /**
+ * Set the text that should be shown in the actual color panel.
+ * Set to null to disable text.
+ *
+ * @param text Text that should be shown.
+ */
+ public void setCurrentColorText(String text) {
+ this.mCurrentLabelText = text;
+ this.tvCurrent.setText(this.mCurrentLabelText);
+ }
+
+ /**
+ * Set the text that should be shown in the new color panel.
+ * Set to null to disable text.
+ *
+ * @param text Text that should be shown.
+ */
+ public void setNewColorText(String text) {
+ this.mNewLabelText = text;
+ this.tvNew.setText(this.mNewLabelText);
+ }
+
+ /**
+ * Set the text that should be shown in the label of the color input.
+ * Set to null to disable text.
+ *
+ * @param text Text that should be shown.
+ */
+ public void setColorLabelText(String text) {
+ this.mColorLabelText = text;
+ this.tvColorLabel.setText(this.mColorLabelText);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onColorChanged(int color) {
+ this.mNewColorView.setColor(color);
+ this.etColor.removeTextChangedListener(this);
+ this.etColor.setText(toHex(this.mNewColorView.getColor()));
+ this.etColor.addTextChangedListener(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {/**NON BLOCK**/}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {/**NON BLOCK**/}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (s.length() == 8) {
+ try {
+ setColor(toARGB(s.toString()), true);
+ } catch (Exception e) {/**NON BLOCK**/}
+ }
+ }
+
+ /**
+ * This method converts dp unit to equivalent device specific value in pixels.
+ *
+ * @param ctx The current context
+ * @param dp A value in dp (Device independent pixels) unit
+ * @return float A float value to represent Pixels equivalent to dp according to device
+ */
+ private float convertDpToPixel(float dp) {
+ Resources resources = getContext().getResources();
+ DisplayMetrics metrics = resources.getDisplayMetrics();
+ return dp * (metrics.densityDpi / 160f);
+ }
+
+ /**
+ * Method that converts an ARGB color to its hex string color representation
+ *
+ * @param argb The ARGB color
+ * @return String The hex string representation of the color
+ */
+ private static String toHex(int argb) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(toHexString((byte)Color.alpha(argb)));
+ sb.append(toHexString((byte)Color.red(argb)));
+ sb.append(toHexString((byte)Color.green(argb)));
+ sb.append(toHexString((byte)Color.blue(argb)));
+ return sb.toString();
+ }
+
+ /**
+ * Method that converts an hex string color representation to an ARGB color
+ *
+ * @param hex The hex string representation of the color
+ * @return int The ARGB color
+ */
+ private static int toARGB(String hex) {
+ return Color.parseColor("#" + hex); //$NON-NLS-1$
+ }
+
+ /**
+ * Method that converts a byte into its hex string representation
+ *
+ * @param v The value to convert
+ * @return String The hex string representation
+ */
+ private static String toHexString(byte v) {
+ String hex = Integer.toHexString(v & 0xff);
+ if (hex.length() == 1) {
+ hex = "0" + hex; //$NON-NLS-1$
+ }
+ return hex.toUpperCase();
+ }
+}
diff --git a/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPanelView.java b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPanelView.java
new file mode 100644
index 00000000..9764ff1d
--- /dev/null
+++ b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPanelView.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2010 Daniel Nilsson
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package afzkl.development.mColorPicker.views;
+
+import afzkl.development.mColorPicker.drawables.AlphaPatternDrawable;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * This class draws a panel which which will be filled with a color which can be set.
+ * It can be used to show the currently selected color which you will get from
+ * the {@link ColorPickerView}.
+ * @author Daniel Nilsson
+ *
+ */
+@SuppressWarnings("all")
+public class ColorPanelView extends View{
+
+ /**
+ * The width in pixels of the border
+ * surrounding the color panel.
+ */
+ private final static float BORDER_WIDTH_PX = 1;
+
+ private static float mDensity = 1f;
+
+ private int mBorderColor = 0xff6E6E6E;
+ private int mColor = 0xff000000;
+
+ private Paint mBorderPaint;
+ private Paint mColorPaint;
+
+ private RectF mDrawingRect;
+ private RectF mColorRect;
+
+ private AlphaPatternDrawable mAlphaPattern;
+
+
+ public ColorPanelView(Context context) {
+ this(context, null);
+ }
+
+ public ColorPanelView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ColorPanelView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ init();
+ }
+
+ private void init() {
+ mBorderPaint = new Paint();
+ mColorPaint = new Paint();
+ mDensity = getContext().getResources().getDisplayMetrics().density;
+ }
+
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+
+ final RectF rect = mColorRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(mDrawingRect, mBorderPaint);
+ }
+
+ if (mAlphaPattern != null) {
+ mAlphaPattern.draw(canvas);
+ }
+
+ mColorPaint.setColor(mColor);
+
+ canvas.drawRect(rect, mColorPaint);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ mDrawingRect = new RectF();
+ mDrawingRect.left = getPaddingLeft();
+ mDrawingRect.right = w - getPaddingRight();
+ mDrawingRect.top = getPaddingTop();
+ mDrawingRect.bottom = h - getPaddingBottom();
+
+ setUpColorRect();
+
+ }
+
+ private void setUpColorRect() {
+ final RectF dRect = mDrawingRect;
+
+ float left = dRect.left + BORDER_WIDTH_PX;
+ float top = dRect.top + BORDER_WIDTH_PX;
+ float bottom = dRect.bottom - BORDER_WIDTH_PX;
+ float right = dRect.right - BORDER_WIDTH_PX;
+
+ mColorRect = new RectF(left,top, right, bottom);
+
+ mAlphaPattern = new AlphaPatternDrawable((int)(5 * mDensity));
+
+ mAlphaPattern.setBounds(Math.round(mColorRect.left),
+ Math.round(mColorRect.top),
+ Math.round(mColorRect.right),
+ Math.round(mColorRect.bottom));
+
+ }
+
+ /**
+ * Set the color that should be shown by this view.
+ * @param color
+ */
+ public void setColor(int color) {
+ mColor = color;
+ invalidate();
+ }
+
+ /**
+ * Get the color currently show by this view.
+ * @return
+ */
+ public int getColor() {
+ return mColor;
+ }
+
+ /**
+ * Set the color of the border surrounding the panel.
+ * @param color
+ */
+ public void setBorderColor(int color) {
+ mBorderColor = color;
+ invalidate();
+ }
+
+ /**
+ * Get the color of the border surrounding the panel.
+ */
+ public int getBorderColor() {
+ return mBorderColor;
+ }
+
+}
diff --git a/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPickerView.java b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPickerView.java
new file mode 100644
index 00000000..eb216c88
--- /dev/null
+++ b/libs/color-picker-view/src/afzkl/development/mColorPicker/views/ColorPickerView.java
@@ -0,0 +1,998 @@
+/*
+ * Copyright (C) 2010 Daniel Nilsson
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package afzkl.development.mColorPicker.views;
+
+import afzkl.development.mColorPicker.drawables.AlphaPatternDrawable;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ComposeShader;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.Shader.TileMode;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.lang.reflect.Method;
+
+/**
+ * Displays a color picker to the user and allow them
+ * to select a color. A slider for the alpha channel is
+ * also available. Enable it by setting
+ * setAlphaSliderVisible(boolean) to true.
+ * @author Daniel Nilsson
+ */
+@SuppressWarnings("all")
+public class ColorPickerView extends View{
+
+ public interface OnColorChangedListener{
+ public void onColorChanged(int color);
+ }
+
+ private final static int PANEL_SAT_VAL = 0;
+ private final static int PANEL_HUE = 1;
+ private final static int PANEL_ALPHA = 2;
+
+ /**
+ * The width in pixels of the border
+ * surrounding all color panels.
+ */
+ private final static float BORDER_WIDTH_PX = 1;
+
+ /**
+ * The width in dp of the hue panel.
+ */
+ private float HUE_PANEL_WIDTH = 30f;
+ /**
+ * The height in dp of the alpha panel
+ */
+ private float ALPHA_PANEL_HEIGHT = 20f;
+ /**
+ * The distance in dp between the different
+ * color panels.
+ */
+ private float PANEL_SPACING = 10f;
+ /**
+ * The radius in dp of the color palette tracker circle.
+ */
+ private float PALETTE_CIRCLE_TRACKER_RADIUS = 5f;
+ /**
+ * The dp which the tracker of the hue or alpha panel
+ * will extend outside of its bounds.
+ */
+ private float RECTANGLE_TRACKER_OFFSET = 2f;
+
+
+ private static float mDensity = 1f;
+
+ private OnColorChangedListener mListener;
+
+ private Paint mSatValPaint;
+ private Paint mSatValTrackerPaint;
+
+ private Paint mHuePaint;
+ private Paint mHueTrackerPaint;
+
+ private Paint mAlphaPaint;
+ private Paint mAlphaTextPaint;
+
+ private Paint mBorderPaint;
+
+ private Shader mValShader;
+ private Shader mSatShader;
+ private Shader mHueShader;
+ private Shader mAlphaShader;
+
+ private int mAlpha = 0xff;
+ private float mHue = 360f;
+ private float mSat = 0f;
+ private float mVal = 0f;
+
+ private String mAlphaSliderText = "Alpha";
+ private int mSliderTrackerColor = 0xff1c1c1c;
+ private int mBorderColor = 0xff6E6E6E;
+ private boolean mShowAlphaPanel = false;
+
+ /*
+ * To remember which panel that has the "focus" when
+ * processing hardware button data.
+ */
+ private int mLastTouchedPanel = PANEL_SAT_VAL;
+
+ /**
+ * Offset from the edge we must have or else
+ * the finger tracker will get clipped when
+ * it is drawn outside of the view.
+ */
+ private float mDrawingOffset;
+
+
+ /*
+ * Distance form the edges of the view
+ * of where we are allowed to draw.
+ */
+ private RectF mDrawingRect;
+
+ private RectF mSatValRect;
+ private RectF mHueRect;
+ private RectF mAlphaRect;
+
+ private AlphaPatternDrawable mAlphaPattern;
+
+ private Point mStartTouchPoint = null;
+
+
+ public ColorPickerView(Context context) {
+ this(context, null);
+ }
+
+ public ColorPickerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ColorPickerView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ mDensity = getContext().getResources().getDisplayMetrics().density;
+ PALETTE_CIRCLE_TRACKER_RADIUS *= mDensity;
+ RECTANGLE_TRACKER_OFFSET *= mDensity;
+ HUE_PANEL_WIDTH *= mDensity;
+ ALPHA_PANEL_HEIGHT *= mDensity;
+ PANEL_SPACING = PANEL_SPACING * mDensity;
+
+ mDrawingOffset = calculateRequiredOffset();
+
+ initPaintTools();
+
+ //Needed for receiving trackball motion events.
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ }
+
+ private void initPaintTools() {
+
+ mSatValPaint = new Paint();
+ mSatValTrackerPaint = new Paint();
+ mHuePaint = new Paint();
+ mHueTrackerPaint = new Paint();
+ mAlphaPaint = new Paint();
+ mAlphaTextPaint = new Paint();
+ mBorderPaint = new Paint();
+
+
+ mSatValTrackerPaint.setStyle(Style.STROKE);
+ mSatValTrackerPaint.setStrokeWidth(2f * mDensity);
+ mSatValTrackerPaint.setAntiAlias(true);
+
+ mHueTrackerPaint.setColor(mSliderTrackerColor);
+ mHueTrackerPaint.setStyle(Style.STROKE);
+ mHueTrackerPaint.setStrokeWidth(2f * mDensity);
+ mHueTrackerPaint.setAntiAlias(true);
+
+ mAlphaTextPaint.setColor(0xff1c1c1c);
+ mAlphaTextPaint.setTextSize(14f * mDensity);
+ mAlphaTextPaint.setAntiAlias(true);
+ mAlphaTextPaint.setTextAlign(Align.CENTER);
+ mAlphaTextPaint.setFakeBoldText(true);
+
+
+ }
+
+ private float calculateRequiredOffset() {
+ float offset = Math.max(PALETTE_CIRCLE_TRACKER_RADIUS, RECTANGLE_TRACKER_OFFSET);
+ offset = Math.max(offset, BORDER_WIDTH_PX * mDensity);
+
+ return offset * 1.5f;
+ }
+
+ private int[] buildHueColorArray() {
+
+ int[] hue = new int[361];
+
+ int count = 0;
+ for (int i = hue.length -1; i >= 0; i--, count++) {
+ hue[count] = Color.HSVToColor(new float[]{i, 1f, 1f});
+ }
+
+ return hue;
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ checkHardwareAccelerationSupport();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+
+ if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0) return;
+
+ drawSatValPanel(canvas);
+ drawHuePanel(canvas);
+ drawAlphaPanel(canvas);
+
+ }
+
+ private void drawSatValPanel(Canvas canvas) {
+
+ final RectF rect = mSatValRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(mDrawingRect.left, mDrawingRect.top, rect.right + BORDER_WIDTH_PX, rect.bottom + BORDER_WIDTH_PX, mBorderPaint);
+ }
+
+ if (mValShader == null) {
+ mValShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
+ 0xffffffff, 0xff000000, TileMode.CLAMP);
+ }
+
+ int rgb = Color.HSVToColor(new float[]{mHue,1f,1f});
+
+ mSatShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
+ 0xffffffff, rgb, TileMode.CLAMP);
+ ComposeShader mShader = new ComposeShader(mValShader, mSatShader, PorterDuff.Mode.MULTIPLY);
+ mSatValPaint.setShader(mShader);
+
+ canvas.drawRect(rect, mSatValPaint);
+
+ Point p = satValToPoint(mSat, mVal);
+
+ mSatValTrackerPaint.setColor(0xff000000);
+ canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS - 1f * mDensity, mSatValTrackerPaint);
+
+ mSatValTrackerPaint.setColor(0xffdddddd);
+ canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS, mSatValTrackerPaint);
+
+ }
+
+ private void drawHuePanel(Canvas canvas) {
+
+ final RectF rect = mHueRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(rect.left - BORDER_WIDTH_PX,
+ rect.top - BORDER_WIDTH_PX,
+ rect.right + BORDER_WIDTH_PX,
+ rect.bottom + BORDER_WIDTH_PX,
+ mBorderPaint);
+ }
+
+ if (mHueShader == null) {
+ mHueShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom, buildHueColorArray(), null, TileMode.CLAMP);
+ mHuePaint.setShader(mHueShader);
+ }
+
+ canvas.drawRect(rect, mHuePaint);
+
+ float rectHeight = 4 * mDensity / 2;
+
+ Point p = hueToPoint(mHue);
+
+ RectF r = new RectF();
+ r.left = rect.left - RECTANGLE_TRACKER_OFFSET;
+ r.right = rect.right + RECTANGLE_TRACKER_OFFSET;
+ r.top = p.y - rectHeight;
+ r.bottom = p.y + rectHeight;
+
+
+ canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
+
+ }
+
+ private void drawAlphaPanel(Canvas canvas) {
+
+ if (!mShowAlphaPanel || mAlphaRect == null || mAlphaPattern == null) return;
+
+ final RectF rect = mAlphaRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(rect.left - BORDER_WIDTH_PX,
+ rect.top - BORDER_WIDTH_PX,
+ rect.right + BORDER_WIDTH_PX,
+ rect.bottom + BORDER_WIDTH_PX,
+ mBorderPaint);
+ }
+
+
+ mAlphaPattern.draw(canvas);
+
+ float[] hsv = new float[]{mHue,mSat,mVal};
+ int color = Color.HSVToColor(hsv);
+ int acolor = Color.HSVToColor(0, hsv);
+
+ mAlphaShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
+ color, acolor, TileMode.CLAMP);
+
+
+ mAlphaPaint.setShader(mAlphaShader);
+
+ canvas.drawRect(rect, mAlphaPaint);
+
+ if (mAlphaSliderText != null && mAlphaSliderText!= "") {
+ canvas.drawText(mAlphaSliderText, rect.centerX(), rect.centerY() + 4 * mDensity, mAlphaTextPaint);
+ }
+
+ float rectWidth = 4 * mDensity / 2;
+
+ Point p = alphaToPoint(mAlpha);
+
+ RectF r = new RectF();
+ r.left = p.x - rectWidth;
+ r.right = p.x + rectWidth;
+ r.top = rect.top - RECTANGLE_TRACKER_OFFSET;
+ r.bottom = rect.bottom + RECTANGLE_TRACKER_OFFSET;
+
+ canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
+
+ }
+
+
+ private Point hueToPoint(float hue) {
+
+ final RectF rect = mHueRect;
+ final float height = rect.height();
+
+ Point p = new Point();
+
+ p.y = (int) (height - (hue * height / 360f) + rect.top);
+ p.x = (int) rect.left;
+
+ return p;
+ }
+
+ private Point satValToPoint(float sat, float val) {
+
+ final RectF rect = mSatValRect;
+ final float height = rect.height();
+ final float width = rect.width();
+
+ Point p = new Point();
+
+ p.x = (int) (sat * width + rect.left);
+ p.y = (int) ((1f - val) * height + rect.top);
+
+ return p;
+ }
+
+ private Point alphaToPoint(int alpha) {
+
+ final RectF rect = mAlphaRect;
+ final float width = rect.width();
+
+ Point p = new Point();
+
+ p.x = (int) (width - (alpha * width / 0xff) + rect.left);
+ p.y = (int) rect.top;
+
+ return p;
+
+ }
+
+ private float[] pointToSatVal(float x, float y) {
+
+ final RectF rect = mSatValRect;
+ float[] result = new float[2];
+
+ float width = rect.width();
+ float height = rect.height();
+
+ if (x < rect.left) {
+ x = 0f;
+ }
+ else if (x > rect.right) {
+ x = width;
+ }
+ else{
+ x = x - rect.left;
+ }
+
+ if (y < rect.top) {
+ y = 0f;
+ }
+ else if (y > rect.bottom) {
+ y = height;
+ }
+ else{
+ y = y - rect.top;
+ }
+
+
+ result[0] = 1.f / width * x;
+ result[1] = 1.f - (1.f / height * y);
+
+ return result;
+ }
+
+ private float pointToHue(float y) {
+
+ final RectF rect = mHueRect;
+
+ float height = rect.height();
+
+ if (y < rect.top) {
+ y = 0f;
+ }
+ else if (y > rect.bottom) {
+ y = height;
+ }
+ else{
+ y = y - rect.top;
+ }
+
+ return 360f - (y * 360f / height);
+ }
+
+ private int pointToAlpha(int x) {
+
+ final RectF rect = mAlphaRect;
+ final int width = (int) rect.width();
+
+ if (x < rect.left) {
+ x = 0;
+ }
+ else if (x > rect.right) {
+ x = width;
+ }
+ else{
+ x = x - (int)rect.left;
+ }
+
+ return 0xff - (x * 0xff / width);
+
+ }
+
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+
+ float x = event.getX();
+ float y = event.getY();
+
+ boolean update = false;
+
+
+ if (event.getAction() == MotionEvent.ACTION_MOVE) {
+
+ switch(mLastTouchedPanel) {
+
+ case PANEL_SAT_VAL:
+
+ float sat, val;
+
+ sat = mSat + x/50f;
+ val = mVal - y/50f;
+
+ if (sat < 0f) {
+ sat = 0f;
+ }
+ else if (sat > 1f) {
+ sat = 1f;
+ }
+
+ if (val < 0f) {
+ val = 0f;
+ }
+ else if (val > 1f) {
+ val = 1f;
+ }
+
+ mSat = sat;
+ mVal = val;
+
+ update = true;
+
+ break;
+
+ case PANEL_HUE:
+
+ float hue = mHue - y * 10f;
+
+ if (hue < 0f) {
+ hue = 0f;
+ }
+ else if (hue > 360f) {
+ hue = 360f;
+ }
+
+ mHue = hue;
+
+ update = true;
+
+ break;
+
+ case PANEL_ALPHA:
+
+ if (!mShowAlphaPanel || mAlphaRect == null) {
+ update = false;
+ }
+ else{
+
+ int alpha = (int) (mAlpha - x*10);
+
+ if (alpha < 0) {
+ alpha = 0;
+ }
+ else if (alpha > 0xff) {
+ alpha = 0xff;
+ }
+
+ mAlpha = alpha;
+
+
+ update = true;
+ }
+
+ break;
+ }
+
+
+ }
+
+
+ if (update) {
+
+ if (mListener != null) {
+ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));
+ }
+
+ invalidate();
+ return true;
+ }
+
+
+ return super.onTrackballEvent(event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+
+ boolean update = false;
+
+ switch(event.getAction()) {
+
+ case MotionEvent.ACTION_DOWN:
+
+ mStartTouchPoint = new Point((int)event.getX(), (int)event.getY());
+
+ update = moveTrackersIfNeeded(event);
+
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+
+ update = moveTrackersIfNeeded(event);
+
+ break;
+
+ case MotionEvent.ACTION_UP:
+
+ mStartTouchPoint = null;
+
+ update = moveTrackersIfNeeded(event);
+
+ break;
+
+ }
+
+ if (update) {
+
+ if (mListener != null) {
+ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));
+ }
+
+ invalidate();
+ return true;
+ }
+
+
+ return super.onTouchEvent(event);
+ }
+
+ private boolean moveTrackersIfNeeded(MotionEvent event) {
+
+ if (mStartTouchPoint == null) return false;
+
+ boolean update = false;
+
+ int startX = mStartTouchPoint.x;
+ int startY = mStartTouchPoint.y;
+
+
+ if (mHueRect.contains(startX, startY)) {
+ mLastTouchedPanel = PANEL_HUE;
+
+ mHue = pointToHue(event.getY());
+
+ update = true;
+ }
+ else if (mSatValRect.contains(startX, startY)) {
+
+ mLastTouchedPanel = PANEL_SAT_VAL;
+
+ float[] result = pointToSatVal(event.getX(), event.getY());
+
+ mSat = result[0];
+ mVal = result[1];
+
+ update = true;
+ }
+ else if (mAlphaRect != null && mAlphaRect.contains(startX, startY)) {
+
+ mLastTouchedPanel = PANEL_ALPHA;
+
+ mAlpha = pointToAlpha((int)event.getX());
+
+ update = true;
+ }
+
+
+ return update;
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+
+ int width = 0;
+ int height = 0;
+
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+
+ int widthAllowed = MeasureSpec.getSize(widthMeasureSpec);
+ int heightAllowed = MeasureSpec.getSize(heightMeasureSpec);
+
+
+ widthAllowed = chooseWidth(widthMode, widthAllowed);
+ heightAllowed = chooseHeight(heightMode, heightAllowed);
+
+
+ if (!mShowAlphaPanel) {
+ height = (int) (widthAllowed - PANEL_SPACING - HUE_PANEL_WIDTH);
+
+ //If calculated height (based on the width) is more than the allowed height.
+ if (height > heightAllowed) {
+ height = heightAllowed;
+ width = (int) (height + PANEL_SPACING + HUE_PANEL_WIDTH);
+ }
+ else{
+ width = widthAllowed;
+ }
+ }
+ else{
+
+ width = (int) (heightAllowed - ALPHA_PANEL_HEIGHT + HUE_PANEL_WIDTH);
+
+ if (width > widthAllowed) {
+ width = widthAllowed;
+ height = (int) (widthAllowed - HUE_PANEL_WIDTH + ALPHA_PANEL_HEIGHT);
+ }
+ else{
+ height = heightAllowed;
+ }
+
+
+ }
+
+
+ setMeasuredDimension(width, height);
+ }
+
+ private int chooseWidth(int mode, int size) {
+ if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
+ return size;
+ } else { // (mode == MeasureSpec.UNSPECIFIED)
+ return getPrefferedWidth();
+ }
+ }
+
+ private int chooseHeight(int mode, int size) {
+ if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
+ return size;
+ } else { // (mode == MeasureSpec.UNSPECIFIED)
+ return getPreferedHeight();
+ }
+ }
+
+ private int getPrefferedWidth() {
+
+ int width = getPreferedHeight();
+
+ if (mShowAlphaPanel) {
+ width -= (PANEL_SPACING + ALPHA_PANEL_HEIGHT);
+ }
+
+
+ return (int) (width + HUE_PANEL_WIDTH + PANEL_SPACING);
+
+ }
+
+ private int getPreferedHeight() {
+
+ int height = (int)(200 * mDensity);
+
+ if (mShowAlphaPanel) {
+ height += PANEL_SPACING + ALPHA_PANEL_HEIGHT;
+ }
+
+ return height;
+ }
+
+
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ mDrawingRect = new RectF();
+ mDrawingRect.left = mDrawingOffset + getPaddingLeft();
+ mDrawingRect.right = w - mDrawingOffset - getPaddingRight();
+ mDrawingRect.top = mDrawingOffset + getPaddingTop();
+ mDrawingRect.bottom = h - mDrawingOffset - getPaddingBottom();
+
+ setUpSatValRect();
+ setUpHueRect();
+ setUpAlphaRect();
+ }
+
+ private void setUpSatValRect() {
+
+ final RectF dRect = mDrawingRect;
+ float panelSide = dRect.height() - BORDER_WIDTH_PX * 2;
+
+ if (mShowAlphaPanel) {
+ panelSide -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
+ }
+
+ float left = dRect.left + BORDER_WIDTH_PX;
+ float top = dRect.top + BORDER_WIDTH_PX;
+ float bottom = top + panelSide;
+ float right = left + panelSide;
+
+ mSatValRect = new RectF(left,top, right, bottom);
+ }
+
+ private void setUpHueRect() {
+ final RectF dRect = mDrawingRect;
+
+ float left = dRect.right - HUE_PANEL_WIDTH + BORDER_WIDTH_PX;
+ float top = dRect.top + BORDER_WIDTH_PX;
+ float bottom = dRect.bottom - BORDER_WIDTH_PX - (mShowAlphaPanel ? (PANEL_SPACING + ALPHA_PANEL_HEIGHT) : 0);
+ float right = dRect.right - BORDER_WIDTH_PX;
+
+ mHueRect = new RectF(left, top, right, bottom);
+ }
+
+ private void setUpAlphaRect() {
+
+ if (!mShowAlphaPanel) return;
+
+ final RectF dRect = mDrawingRect;
+
+ float left = dRect.left + BORDER_WIDTH_PX;
+ float top = dRect.bottom - ALPHA_PANEL_HEIGHT + BORDER_WIDTH_PX;
+ float bottom = dRect.bottom - BORDER_WIDTH_PX;
+ float right = dRect.right - BORDER_WIDTH_PX;
+
+ mAlphaRect = new RectF(left, top, right, bottom);
+
+
+ mAlphaPattern = new AlphaPatternDrawable((int) (5 * mDensity));
+ mAlphaPattern.setBounds(Math.round(mAlphaRect.left), Math
+ .round(mAlphaRect.top), Math.round(mAlphaRect.right), Math
+ .round(mAlphaRect.bottom));
+
+
+
+ }
+
+
+ /**
+ * Set a OnColorChangedListener to get notified when the color
+ * selected by the user has changed.
+ * @param listener
+ */
+ public void setOnColorChangedListener(OnColorChangedListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Set the color of the border surrounding all panels.
+ * @param color
+ */
+ public void setBorderColor(int color) {
+ mBorderColor = color;
+ invalidate();
+ }
+
+ /**
+ * Get the color of the border surrounding all panels.
+ */
+ public int getBorderColor() {
+ return mBorderColor;
+ }
+
+ /**
+ * Get the current color this view is showing.
+ * @return the current color.
+ */
+ public int getColor() {
+ return Color.HSVToColor(mAlpha, new float[]{mHue,mSat,mVal});
+ }
+
+ /**
+ * Set the color the view should show.
+ * @param color The color that should be selected.
+ */
+ public void setColor(int color) {
+ setColor(color, false);
+ }
+
+ /**
+ * Set the color this view should show.
+ * @param color The color that should be selected.
+ * @param callback If you want to get a callback to
+ * your OnColorChangedListener.
+ */
+ public void setColor(int color, boolean callback) {
+
+ int alpha = Color.alpha(color);
+ int red = Color.red(color);
+ int blue = Color.blue(color);
+ int green = Color.green(color);
+
+ float[] hsv = new float[3];
+
+ Color.RGBToHSV(red, green, blue, hsv);
+
+ mAlpha = alpha;
+ mHue = hsv[0];
+ mSat = hsv[1];
+ mVal = hsv[2];
+
+ if (callback && mListener != null) {
+ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));
+ }
+
+ invalidate();
+ }
+
+ /**
+ * Get the drawing offset of the color picker view.
+ * The drawing offset is the distance from the side of
+ * a panel to the side of the view minus the padding.
+ * Useful if you want to have your own panel below showing
+ * the currently selected color and want to align it perfectly.
+ * @return The offset in pixels.
+ */
+ public float getDrawingOffset() {
+ return mDrawingOffset;
+ }
+
+ /**
+ * Set if the user is allowed to adjust the alpha panel. Default is false.
+ * If it is set to false no alpha will be set.
+ * @param visible
+ */
+ public void setAlphaSliderVisible(boolean visible) {
+
+ if (mShowAlphaPanel != visible) {
+ mShowAlphaPanel = visible;
+
+ /*
+ * Reset all shader to force a recreation.
+ * Otherwise they will not look right after
+ * the size of the view has changed.
+ */
+ mValShader = null;
+ mSatShader = null;
+ mHueShader = null;
+ mAlphaShader = null;;
+
+ requestLayout();
+ }
+
+ }
+
+ public void setSliderTrackerColor(int color) {
+ mSliderTrackerColor = color;
+
+ mHueTrackerPaint.setColor(mSliderTrackerColor);
+
+ invalidate();
+ }
+
+ public int getSliderTrackerColor() {
+ return mSliderTrackerColor;
+ }
+
+ /**
+ * Set the text that should be shown in the
+ * alpha slider. Set to null to disable text.
+ * @param res string resource id.
+ */
+ public void setAlphaSliderText(int res) {
+ String text = getContext().getString(res);
+ setAlphaSliderText(text);
+ }
+
+ /**
+ * Set the text that should be shown in the
+ * alpha slider. Set to null to disable text.
+ * @param text Text that should be shown.
+ */
+ public void setAlphaSliderText(String text) {
+ mAlphaSliderText = text;
+ invalidate();
+ }
+
+ /**
+ * Get the current value of the text
+ * that will be shown in the alpha
+ * slider.
+ * @return
+ */
+ public String getAlphaSliderText() {
+ return mAlphaSliderText;
+ }
+
+ /**
+ * Method that checks the support for HardwareAcceleration. Check AOSP notice<br/>
+ * <br/>
+ * <pre>
+ * 'ComposeShader can only contain shaders of different types (a BitmapShader and a
+ * LinearGradient for instance, but not two instances of BitmapShader)'. But, 'If your
+ * application is affected by any of these missing features or limitations, you can turn
+ * off hardware acceleration for just the affected portion of your application by calling
+ * setLayerType(View.LAYER_TYPE_SOFTWARE, null).'
+ */
+ private void checkHardwareAccelerationSupport() {
+ // HardwareAcceleration sit is only available since ICS. 14 = ICS_VERSION_CODE
+ if (android.os.Build.VERSION.SDK_INT >= 14) {
+ try{
+ // We need to use reflection to get that method to avoid compilation errors
+ Method isHardwareAccelerated =
+ getClass().getMethod("isHardwareAccelerated", new Class[]{});
+ Object o = isHardwareAccelerated.invoke(this, new Object[]{});
+ if (null != o && o instanceof Boolean && (Boolean)o) {
+ // HardwareAcceleration is supported. Use SoftwareAcceleration
+ Method setLayerType =
+ getClass().getMethod(
+ "setLayerType", int.class, android.graphics.Paint.class);
+ setLayerType.invoke(this, 1, new Object[]{});
+ }
+ } catch (Exception e) { /** NON BLOCK **/}
+ }
+ }
+
+}
diff --git a/res/layout/color_picker_pref_item.xml b/res/layout/color_picker_pref_item.xml
new file mode 100644
index 00000000..02c44c1a
--- /dev/null
+++ b/res/layout/color_picker_pref_item.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="48dp"
+ android:layout_height="32dp"
+ android:background="@android:color/darker_gray">
+ <afzkl.development.mColorPicker.views.ColorPanelView
+ android:id="@+android:id/color_picker"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="1dp"
+ android:layout_gravity="center"
+ android:focusable="false"
+ android:clickable="false" />
+</LinearLayout>
+
diff --git a/res/menu/editor.xml b/res/menu/editor.xml
index 960d305d..654187ac 100644
--- a/res/menu/editor.xml
+++ b/res/menu/editor.xml
@@ -16,11 +16,21 @@
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
+ android:id="@+id/mnu_no_suggestions"
+ android:showAsAction="never"
+ android:checkable="true"
+ android:title="@string/menu_no_suggestions"/>
+ <item
android:id="@+id/mnu_word_wrap"
android:showAsAction="never"
android:checkable="true"
android:title="@string/menu_word_wrap"/>
<item
+ android:id="@+id/mnu_syntax_highlight"
+ android:showAsAction="never"
+ android:checkable="true"
+ android:title="@string/menu_syntax_highlight"/>
+ <item
android:id="@+id/mnu_settings"
android:showAsAction="never"
android:title="@string/menu_settings"/>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7f524ce0..c8566788 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -425,8 +425,12 @@
<string name="menu_settings">Settings</string>
<!-- Menu * History * Clear history -->
<string name="menu_clear_history">Clear history</string>
+ <!-- Menu * Editor * No suggestions -->
+ <string name="menu_no_suggestions">No suggestions</string>
<!-- Menu * Editor * Word wrap -->
<string name="menu_word_wrap">Word wrap</string>
+ <!-- Menu * Editor * Sintax highlight -->
+ <string name="menu_syntax_highlight">Syntax highlight</string>
<!-- Regular expression for create copy action -->
<string name="create_copy_regexp">
@@ -737,8 +741,34 @@
<string name="pref_remove_saved_search_terms_msg">All saved search terms were removed.</string>
<!-- Preferences * Editor * Behaviour category -->
<string name="pref_editor_behaviour_category">Behaviour</string>
+ <!-- Preferences * Editor * No suggestions -->
+ <string name="pref_no_suggestions">No suggestions</string>
+ <!-- Preferences * Editor * No suggestions summary -->
+ <string name="pref_no_suggestions_desc">Do not display dictionary suggestions while editing the file</string>
<!-- Preferences * Editor * Word wrap -->
<string name="pref_word_wrap">Word wrap</string>
+ <!-- Preferences * Editor * Hexdump -->
+ <string name="pref_hexdump">Hexdump binary files</string>
+ <!-- Preferences * Editor * Hexdump desc -->
+ <string name="pref_hexdump_desc">When opening a binary file, generate an hexdump of the file
+ and open it in the hex viewer.</string>
+ <!-- Preferences * Editor * Syntax highlight category -->
+ <string name="pref_editor_syntax_highlight_category">Syntax highlight</string>
+ <!-- Preferences * Editor * Syntax highlight -->
+ <string name="pref_syntax_highlight">Syntax highlight</string>
+ <!-- Preferences * Editor * Syntax highlight summary -->
+ <string name="pref_syntax_highlight_desc">Highlight the syntax of the file displayed in
+ the editor (only when a syntax highlight processor is available for the type of file)</string>
+ <!-- Preferences * Editor * Syntax highlight color scheme -->
+ <string name="pref_syntax_highlight_color_scheme">Color scheme</string>
+ <!-- Preferences * Editor * Syntax highlight color scheme summary -->
+ <string name="pref_syntax_highlight_color_scheme_desc">Tap to select the syntax highlight color scheme</string>
+ <!-- Preferences * Editor * Syntax highlight * Color Scheme -->
+ <string name="pref_syntax_sh_use_theme_default">Use theme default</string>
+ <!-- Preferences * Editor * Syntax highlight *Color Scheme summary -->
+ <string name="pref_syntax_sh_use_theme_default_desc">Use the default syntax highlight of the current theme</string>
+ <!-- Preferences * Editor * Syntax highlight * Color Scheme * Items category -->
+ <string name="pref_editor_sh_item_category">Items</string>
<!-- Preferences * Themes * Themes selection category -->
<string name="pref_themes_selection_category">Themes</string>
<!-- Preferences * Themes * Set theme button -->
@@ -760,6 +790,26 @@
<!-- Themes * Default theme author -->
<string name="themes_author">CyanogenMod</string>
+ <!-- ColorPickerDialog -->
+ <!-- The text of the alpha slider control -->
+ <string name="color_picker_alpha_slider_text">Alpha</string>
+ <!-- The label of the current color panel -->
+ <string name="color_picker_current_text">Current:</string>
+ <!-- The label of the new color panel -->
+ <string name="color_picker_new_text">New:</string>
+ <!-- The label of the color input -->
+ <string name="color_picker_color">Color:</string>
+
+ <!-- Android Syntax Highlight -->
+ <string name="ash_reset_color_scheme">Tap to restore the default theme color scheme</string>
+ <string name="ash_text">Text</string>
+ <string name="ash_assignment">Assignment</string>
+ <string name="ash_singleline_comment">Single-Line comment</string>
+ <string name="ash_multiline_comment">Multi-Line comment</string>
+ <string name="ash_keyword">Keyword</string>
+ <string name="ash_quoted_string">Quoted string</string>
+ <string name="ash_variable">Variable</string>
+
<!-- Security * Extract relative or absolute files -->
<string name="security_warning_extract">Warning!\n\n
Extracting an archive file with relative or absolute paths may cause damage to your device
diff --git a/res/values/theme.xml b/res/values/theme.xml
index 629b234c..eeb9b6b9 100644
--- a/res/values/theme.xml
+++ b/res/values/theme.xml
@@ -175,4 +175,14 @@
<drawable name="fso_type_text_drawable">@drawable/fso_type_text</drawable>
<drawable name="fso_type_video_drawable">@drawable/fso_type_video</drawable>
+
+ <!-- Syntax Highlight -->
+ <color name="ash_text_color">@color/black_transparent</color>
+ <color name="ash_assignment_color">@color/black_transparent</color>
+ <color name="ash_singleline_comment_color">#ff278556</color>
+ <color name="ash_multiline_comment_color">#ff7f9fbf</color>
+ <color name="ash_keyword_color">#ff773b63</color>
+ <color name="ash_quoted_string_color">#990000C0</color>
+ <color name="ash_variable_color">#ff5080bd</color>
+
</resources>
diff --git a/res/xml/preferences_editor.xml b/res/xml/preferences_editor.xml
index d4731dcc..350aa953 100644
--- a/res/xml/preferences_editor.xml
+++ b/res/xml/preferences_editor.xml
@@ -22,6 +22,14 @@
android:key="editor_behaviour"
android:title="@string/pref_editor_behaviour_category">
+ <!-- No suggestions -->
+ <CheckBoxPreference
+ android:key="cm_filemanager_editor_no_suggestions"
+ android:title="@string/pref_no_suggestions"
+ android:summary="@string/pref_no_suggestions_desc"
+ android:persistent="true"
+ android:defaultValue="false" />
+
<!-- Word wrap -->
<CheckBoxPreference
android:key="cm_filemanager_editor_word_wrap"
@@ -29,6 +37,37 @@
android:persistent="true"
android:defaultValue="true" />
+ <!-- Hexdump -->
+ <CheckBoxPreference
+ android:key="cm_filemanager_editor_hexdump"
+ android:title="@string/pref_hexdump"
+ android:summary="@string/pref_hexdump_desc"
+ android:persistent="true"
+ android:defaultValue="true" />
+
+ </PreferenceCategory>
+
+ <!-- Editor Syntax Highlight -->
+ <PreferenceCategory
+ android:key="editor_syntax_highlight"
+ android:title="@string/pref_editor_syntax_highlight_category">
+
+ <!-- Syntax highlight -->
+ <CheckBoxPreference
+ android:key="cm_filemanager_editor_syntax_highlight"
+ android:title="@string/pref_syntax_highlight"
+ android:summary="@string/pref_syntax_highlight_desc"
+ android:persistent="true"
+ android:defaultValue="true" />
+
+ <!-- Color scheme -->
+ <PreferenceScreen
+ android:key="cm_filemanager_editor_sh_color_scheme"
+ android:title="@string/pref_syntax_highlight_color_scheme"
+ android:summary="@string/pref_syntax_highlight_color_scheme_desc"
+ android:dependency="cm_filemanager_editor_syntax_highlight"
+ android:fragment="com.cyanogenmod.filemanager.activities.preferences.EditorSHColorSchemePreferenceFragment" />
+
</PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/preferences_editor_color_scheme.xml b/res/xml/preferences_editor_color_scheme.xml
new file mode 100644
index 00000000..6edd0e4c
--- /dev/null
+++ b/res/xml/preferences_editor_color_scheme.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- Use default theme color scheme -->
+ <CheckBoxPreference
+ android:key="cm_filemanager_editor_sh_use_theme_default"
+ android:title="@string/pref_syntax_sh_use_theme_default"
+ android:summary="@string/pref_syntax_sh_use_theme_default_desc"
+ android:persistent="true"
+ android:defaultValue="true" />
+
+ <!-- Editor behaviour -->
+ <PreferenceCategory
+ android:key="editor_sh_items_category"
+ android:title="@string/pref_editor_sh_item_category">
+
+ <!-- Reset color scheme to theme defaults -->
+ <Preference
+ android:key="ash_reset_color_scheme"
+ android:summary="@string/ash_reset_color_scheme"
+ android:persistent="false" />
+
+ <!-- Text -->
+ <com.cyanogenmod.filemanager.ui.preferences.ColorPickerPreference
+ android:key="ash_text"
+ android:title="@string/ash_text"
+ android:persistent="false"
+ android:defaultValue="@color/ash_text_color" />
+
+ <!-- Assignment -->
+ <com.cyanogenmod.filemanager.ui.preferences.ColorPickerPreference
+ android:key="ash_assignment"
+ android:title="@string/ash_assignment"
+ android:persistent="false"
+ android:defaultValue="@color/ash_assignment_color" />
+
+ <!-- Single-Line comment -->
+ <com.cyanogenmod.filemanager.ui.preferences.ColorPickerPreference
+ android:key="ash_singleline_comment"
+ android:title="@string/ash_singleline_comment"
+ android:persistent="false"
+ android:defaultValue="@color/ash_singleline_comment_color" />
+
+ <!-- Multi-Line comment -->
+ <com.cyanogenmod.filemanager.ui.preferences.ColorPickerPreference
+ android:key="ash_multiline_comment"
+ android:title="@string/ash_multiline_comment"
+ android:persistent="false"
+ android:defaultValue="@color/ash_multiline_comment_color" />
+
+ <!-- Keyword -->
+ <com.cyanogenmod.filemanager.ui.preferences.ColorPickerPreference
+ android:key="ash_keyword"
+ android:title="@string/ash_keyword"
+ android:persistent="false"
+ android:defaultValue="@color/ash_keyword_color" />
+
+ <!-- Quoted string -->
+ <com.cyanogenmod.filemanager.ui.preferences.ColorPickerPreference
+ android:key="ash_quoted_string"
+ android:title="@string/ash_quoted_string"
+ android:persistent="false"
+ android:defaultValue="@color/ash_quoted_string_color" />
+
+ <!-- Variable -->
+ <com.cyanogenmod.filemanager.ui.preferences.ColorPickerPreference
+ android:key="ash_variable"
+ android:title="@string/ash_variable"
+ android:persistent="false"
+ android:defaultValue="@color/ash_variable_color" />
+
+ </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/res/xml/preferences_headers.xml b/res/xml/preferences_headers.xml
index a28e5842..80c4509d 100644
--- a/res/xml/preferences_headers.xml
+++ b/res/xml/preferences_headers.xml
@@ -16,16 +16,16 @@
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<header
- android:fragment="com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences$GeneralPreferenceFragment"
+ android:fragment="com.cyanogenmod.filemanager.activities.preferences.GeneralPreferenceFragment"
android:title="@string/pref_general" />
<header
- android:fragment="com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences$SearchPreferenceFragment"
+ android:fragment="com.cyanogenmod.filemanager.activities.preferences.SearchPreferenceFragment"
android:title="@string/pref_search" />
<header
- android:fragment="com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences$EditorPreferenceFragment"
+ android:fragment="com.cyanogenmod.filemanager.activities.preferences.EditorPreferenceFragment"
android:title="@string/pref_editor" />
<header
- android:fragment="com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences$ThemesPreferenceFragment"
+ android:fragment="com.cyanogenmod.filemanager.activities.preferences.ThemesPreferenceFragment"
android:title="@string/pref_themes" />
<header
android:title="@string/pref_about"
diff --git a/src/com/cyanogenmod/filemanager/FileManagerApplication.java b/src/com/cyanogenmod/filemanager/FileManagerApplication.java
index cae025e2..3e77be46 100644
--- a/src/com/cyanogenmod/filemanager/FileManagerApplication.java
+++ b/src/com/cyanogenmod/filemanager/FileManagerApplication.java
@@ -314,7 +314,7 @@ public final class FileManagerApplication extends Application {
* @return boolean If the command is present
*/
public static boolean hasOptionalCommand(String commandId) {
- if (!sOptionalCommandsMap.containsKey(commandId)){
+ if (!sOptionalCommandsMap.containsKey(commandId)) {
return false;
}
return sOptionalCommandsMap.get(commandId).booleanValue();
diff --git a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
index 528ce49d..47da72e5 100644
--- a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
@@ -30,8 +30,11 @@ import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
import android.preference.PreferenceActivity;
import android.text.Editable;
+import android.text.InputType;
+import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
@@ -51,10 +54,15 @@ import android.widget.Toast;
import com.android.internal.util.HexDump;
import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.activities.preferences.EditorPreferenceFragment;
+import com.cyanogenmod.filemanager.activities.preferences.EditorSHColorSchemePreferenceFragment;
import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
-import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences.EditorPreferenceFragment;
import com.cyanogenmod.filemanager.adapters.HighlightedSimpleMenuListAdapter;
import com.cyanogenmod.filemanager.adapters.SimpleMenuListAdapter;
+import com.cyanogenmod.filemanager.ash.HighlightColors;
+import com.cyanogenmod.filemanager.ash.ISyntaxHighlightResourcesResolver;
+import com.cyanogenmod.filemanager.ash.SyntaxHighlightFactory;
+import com.cyanogenmod.filemanager.ash.SyntaxHighlightProcessor;
import com.cyanogenmod.filemanager.commands.AsyncResultListener;
import com.cyanogenmod.filemanager.commands.WriteExecutable;
import com.cyanogenmod.filemanager.console.ConsoleBuilder;
@@ -70,6 +78,7 @@ import com.cyanogenmod.filemanager.util.DialogHelper;
import com.cyanogenmod.filemanager.util.ExceptionUtil;
import com.cyanogenmod.filemanager.util.ExceptionUtil.OnRelaunchCommandResult;
import com.cyanogenmod.filemanager.util.FileHelper;
+import com.cyanogenmod.filemanager.util.ResourcesHelper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -99,17 +108,81 @@ public class EditorActivity extends Activity implements TextWatcher {
// The settings has changed
String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
if (key != null) {
+ final EditorActivity activity = EditorActivity.this;
+
+ // No suggestions
+ if (key.compareTo(FileManagerSettings.SETTINGS_EDITOR_NO_SUGGESTIONS.getId()) == 0) {
+ // Ignore in binary files
+ if (activity.mBinary) return;
+
+ // Do we have a different setting?
+ boolean noSuggestionsSetting =
+ Preferences.getSharedPreferences().getBoolean(
+ FileManagerSettings.SETTINGS_EDITOR_NO_SUGGESTIONS.getId(),
+ ((Boolean)FileManagerSettings.SETTINGS_EDITOR_NO_SUGGESTIONS.
+ getDefaultValue()).booleanValue());
+ if (noSuggestionsSetting != activity.mNoSuggestions) {
+ activity.mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ toggleNoSuggestions();
+ }
+ });
+ }
+
// Word wrap
- if (key.compareTo(FileManagerSettings.
- SETTINGS_EDITOR_WORD_WRAP.getId()) == 0) {
+ } else if (key.compareTo(FileManagerSettings.SETTINGS_EDITOR_WORD_WRAP.getId()) == 0) {
+ // Ignore in binary files
+ if (activity.mBinary) return;
+
// Do we have a different setting?
boolean wordWrapSetting = Preferences.getSharedPreferences().getBoolean(
FileManagerSettings.SETTINGS_EDITOR_WORD_WRAP.getId(),
((Boolean)FileManagerSettings.SETTINGS_EDITOR_WORD_WRAP.
getDefaultValue()).booleanValue());
- if (wordWrapSetting != EditorActivity.this.mWordWrap) {
- toggleWordWrap();
+ if (wordWrapSetting != activity.mWordWrap) {
+ activity.mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ toggleWordWrap();
+ }
+ });
+ }
+
+ // Syntax highlight
+ // Default theme color scheme
+ // Color scheme
+ } else if (key.compareTo(FileManagerSettings.SETTINGS_EDITOR_SYNTAX_HIGHLIGHT.getId()) == 0) {
+ // Ignore in binary files
+ if (activity.mBinary) return;
+
+ // Do we have a different setting?
+ boolean syntaxHighlightSetting =
+ Preferences.getSharedPreferences().getBoolean(
+ FileManagerSettings.SETTINGS_EDITOR_SYNTAX_HIGHLIGHT.getId(),
+ ((Boolean)FileManagerSettings.SETTINGS_EDITOR_SYNTAX_HIGHLIGHT.
+ getDefaultValue()).booleanValue());
+ if (syntaxHighlightSetting != activity.mSyntaxHighlight) {
+ activity.mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ toggleSyntaxHighlight();
+ }
+ });
}
+
+ } else if (key.compareTo(FileManagerSettings.SETTINGS_EDITOR_SH_USE_THEME_DEFAULT.getId()) == 0 ||
+ key.compareTo(FileManagerSettings.SETTINGS_EDITOR_SH_COLOR_SCHEME.getId()) == 0 ) {
+ // Ignore in binary files
+ if (activity.mBinary) return;
+
+ // Reload the syntax highlight
+ activity.mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ reloadSyntaxHighlight();
+ }
+ });
}
}
return;
@@ -128,15 +201,14 @@ public class EditorActivity extends Activity implements TextWatcher {
/**
* An internal listener for read a file
*/
- @SuppressWarnings("hiding")
private class AsyncReader implements AsyncResultListener {
final Object mSync = new Object();
ByteArrayOutputStream mByteBuffer = null;
- StringBuilder mBuffer = null;
+ SpannableStringBuilder mBuffer = null;
Exception mCause;
long mSize;
- FileSystemObject mFso;
+ FileSystemObject mReadFso;
OnProgressListener mListener;
/**
@@ -151,7 +223,7 @@ public class EditorActivity extends Activity implements TextWatcher {
*/
@Override
public void onAsyncStart() {
- this.mByteBuffer = new ByteArrayOutputStream((int)this.mFso.getSize());
+ this.mByteBuffer = new ByteArrayOutputStream((int)this.mReadFso.getSize());
this.mSize = 0;
}
@@ -194,10 +266,10 @@ public class EditorActivity extends Activity implements TextWatcher {
this.mByteBuffer.write(partial, 0, partial.length);
this.mSize += partial.length;
- if (this.mListener != null && this.mFso != null) {
+ if (this.mListener != null && this.mReadFso != null) {
int progress = 0;
- if (this.mFso.getSize() != 0) {
- progress = (int)((this.mSize*100) / this.mFso.getSize());
+ if (this.mReadFso.getSize() != 0) {
+ progress = (int)((this.mSize*100) / this.mReadFso.getSize());
}
this.mListener.onProgress(progress);
}
@@ -263,6 +335,89 @@ public class EditorActivity extends Activity implements TextWatcher {
}
/**
+ * An internal class to resolve resources for the syntax highlight library.
+ * @hide
+ */
+ class ResourcesResolver implements ISyntaxHighlightResourcesResolver {
+ @Override
+ public CharSequence getString(String id, String resid) {
+ return EditorActivity.this.getString(
+ ResourcesHelper.getIdentifier(
+ EditorActivity.this.getResources(), "string", resid)); //$NON-NLS-1$
+ }
+
+ @Override
+ public int getInteger(String id, String resid, int def) {
+ return EditorActivity.this.getResources().
+ getInteger(
+ ResourcesHelper.getIdentifier(
+ EditorActivity.this.getResources(), "integer", resid)); //$NON-NLS-1$
+ }
+
+ @Override
+ public int getColor(String id, String resid, int def) {
+ final Context ctx = EditorActivity.this;
+ try {
+ // Is default theme color scheme enabled?
+ if (isDefaultThemeColorScheme()) {
+ return ThemeManager.getCurrentTheme(ctx).getColor(ctx, resid);
+ }
+
+ // Use the user-defined settings
+ int[] colors = getUserColorScheme();
+ HighlightColors[] schemeColors = HighlightColors.values();
+ int cc = schemeColors.length;
+ int cc2 = colors.length;
+ for (int i = 0; i < cc; i++) {
+ if (schemeColors[i].getId().compareTo(id) == 0) {
+ if (cc2 >= i) {
+ // User-defined
+ return colors[i];
+ }
+
+ // Theme default
+ return ThemeManager.getCurrentTheme(ctx).getColor(ctx, resid);
+ }
+
+ }
+
+ } catch (Exception ex) {
+ // Resource not found
+ }
+ return def;
+ }
+
+ /**
+ * Method that returns if we should return the default theme color scheme or not
+ *
+ * @return boolean Whether return the default theme color scheme or not
+ */
+ private boolean isDefaultThemeColorScheme() {
+ Boolean defaultValue =
+ (Boolean)FileManagerSettings.
+ SETTINGS_EDITOR_SH_USE_THEME_DEFAULT.getDefaultValue();
+ return Preferences.getSharedPreferences().getBoolean(
+ FileManagerSettings.SETTINGS_EDITOR_SH_USE_THEME_DEFAULT.getId(),
+ defaultValue.booleanValue());
+ }
+
+ /**
+ * Method that returns the user-defined color scheme
+ *
+ * @return int[] The user-defined color scheme
+ */
+ private int[] getUserColorScheme() {
+ String defaultValue =
+ (String)FileManagerSettings.
+ SETTINGS_EDITOR_SH_COLOR_SCHEME.getDefaultValue();
+ String value = Preferences.getSharedPreferences().getString(
+ FileManagerSettings.SETTINGS_EDITOR_SH_COLOR_SCHEME.getId(),
+ defaultValue);
+ return EditorSHColorSchemePreferenceFragment.toColorShemeArray(value);
+ }
+ }
+
+ /**
* @hide
*/
FileSystemObject mFso;
@@ -308,6 +463,12 @@ public class EditorActivity extends Activity implements TextWatcher {
*/
ButtonItem mSave;
+ // No suggestions status
+ /**
+ * @hide
+ */
+ boolean mNoSuggestions;
+
// Word wrap status
private ViewGroup mWordWrapView;
private ViewGroup mNoWordWrapView;
@@ -316,8 +477,27 @@ public class EditorActivity extends Activity implements TextWatcher {
*/
boolean mWordWrap;
+ // Syntax highlight status
+ /**
+ * @hide
+ */
+ boolean mSyntaxHighlight;
+ /**
+ * @hide
+ */
+ SyntaxHighlightProcessor mSyntaxHighlightProcessor;
+ private int mEditStart;
+ private int mEditEnd;
+
private View mOptionsAnchorView;
+ private final Object mExecSync = new Object();
+
+ /**
+ * @hide
+ */
+ Handler mHandler;
+
private static final char[] VALID_NON_PRINTABLE_CHARS = {' ', '\t', '\r', '\n'};
/**
@@ -339,6 +519,8 @@ public class EditorActivity extends Activity implements TextWatcher {
Log.d(TAG, "EditorActivity.onCreate"); //$NON-NLS-1$
}
+ this.mHandler = new Handler();
+
// Register the broadcast receiver
IntentFilter filter = new IntentFilter();
filter.addAction(FileManagerSettings.INTENT_THEME_CHANGED);
@@ -443,10 +625,22 @@ public class EditorActivity extends Activity implements TextWatcher {
this.mEditor.setEnabled(false);
this.mWordWrapView = (ViewGroup)findViewById(R.id.editor_word_wrap_view);
this.mNoWordWrapView = (ViewGroup)findViewById(R.id.editor_no_word_wrap_view);
- this.mWordWrap = true;
this.mWordWrapView.setVisibility(View.VISIBLE);
this.mNoWordWrapView.setVisibility(View.GONE);
+ this.mNoSuggestions = false;
+ this.mWordWrap = true;
+ this.mSyntaxHighlight = true;
+
+ // Load the no suggestions setting
+ boolean noSuggestionsSetting = Preferences.getSharedPreferences().getBoolean(
+ FileManagerSettings.SETTINGS_EDITOR_NO_SUGGESTIONS.getId(),
+ ((Boolean)FileManagerSettings.SETTINGS_EDITOR_NO_SUGGESTIONS.
+ getDefaultValue()).booleanValue());
+ if (noSuggestionsSetting != this.mNoSuggestions) {
+ toggleNoSuggestions();
+ }
+
// Load the word wrap setting
boolean wordWrapSetting = Preferences.getSharedPreferences().getBoolean(
FileManagerSettings.SETTINGS_EDITOR_WORD_WRAP.getId(),
@@ -456,30 +650,99 @@ public class EditorActivity extends Activity implements TextWatcher {
toggleWordWrap();
}
+ // Load the syntax highlight setting
+ boolean syntaxHighlighSetting = Preferences.getSharedPreferences().getBoolean(
+ FileManagerSettings.SETTINGS_EDITOR_SYNTAX_HIGHLIGHT.getId(),
+ ((Boolean)FileManagerSettings.SETTINGS_EDITOR_SYNTAX_HIGHLIGHT.
+ getDefaultValue()).booleanValue());
+ if (syntaxHighlighSetting != this.mSyntaxHighlight) {
+ toggleSyntaxHighlight();
+ }
+
this.mProgress = findViewById(R.id.editor_progress);
this.mProgressBar = (ProgressBar)findViewById(R.id.editor_progress_bar);
this.mProgressBarMsg = (TextView)findViewById(R.id.editor_progress_msg);
}
/**
+ * Method that toggle the no suggestions property of the editor
+ * @hide
+ */
+ /**package**/ void toggleNoSuggestions() {
+ synchronized (this.mExecSync) {
+ int type = InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_FLAG_MULTI_LINE |
+ InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE;
+ if (!this.mNoSuggestions) {
+ type |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
+ }
+ this.mEditor.setInputType(type);
+ this.mNoSuggestions = !this.mNoSuggestions;
+ }
+ }
+
+ /**
* Method that toggle the word wrap property of the editor
* @hide
*/
/**package**/ void toggleWordWrap() {
- ViewGroup vSrc = this.mWordWrap ? this.mWordWrapView : this.mNoWordWrapView;
- ViewGroup vDst = this.mWordWrap ? this.mNoWordWrapView : this.mWordWrapView;
- ViewGroup vSrcParent = this.mWordWrap
- ? this.mWordWrapView
- : (ViewGroup)this.mNoWordWrapView.getChildAt(0);
- ViewGroup vDstParent = this.mWordWrap
- ? (ViewGroup)this.mNoWordWrapView.getChildAt(0)
- : this.mWordWrapView;
- vSrc.setVisibility(View.GONE);
- vSrcParent.removeView(this.mEditor);
- vDstParent.addView(this.mEditor);
- vDst.setVisibility(View.VISIBLE);
- vDst.scrollTo(0, 0);
- this.mWordWrap = !this.mWordWrap;
+ synchronized (this.mExecSync) {
+ ViewGroup vSrc = this.mWordWrap ? this.mWordWrapView : this.mNoWordWrapView;
+ ViewGroup vDst = this.mWordWrap ? this.mNoWordWrapView : this.mWordWrapView;
+ ViewGroup vSrcParent = this.mWordWrap
+ ? this.mWordWrapView
+ : (ViewGroup)this.mNoWordWrapView.getChildAt(0);
+ ViewGroup vDstParent = this.mWordWrap
+ ? (ViewGroup)this.mNoWordWrapView.getChildAt(0)
+ : this.mWordWrapView;
+ vSrc.setVisibility(View.GONE);
+ vSrcParent.removeView(this.mEditor);
+ vDstParent.addView(this.mEditor);
+ vDst.setVisibility(View.VISIBLE);
+ vDst.scrollTo(0, 0);
+ this.mWordWrap = !this.mWordWrap;
+ }
+ }
+
+ /**
+ * Method that toggles the syntax highlight property of the editor
+ * @hide
+ */
+ /**package**/ void toggleSyntaxHighlight() {
+ synchronized (this.mExecSync) {
+ if (this.mSyntaxHighlightProcessor != null) {
+ try {
+ if (this.mSyntaxHighlight) {
+ this.mSyntaxHighlightProcessor.clear(this.mEditor.getText());
+ } else {
+ this.mSyntaxHighlightProcessor.process(this.mEditor.getText());
+ }
+ } catch (Exception ex) {
+ // An error in a syntax library, should not break down app.
+ Log.e(TAG, "Syntax highlight failed.", ex); //$NON-NLS-1$
+ }
+ }
+
+ this.mSyntaxHighlight = !this.mSyntaxHighlight;
+ }
+ }
+
+ /**
+ * Method that reloads the syntax highlight of the current file
+ * @hide
+ */
+ /**package**/ void reloadSyntaxHighlight() {
+ synchronized (this.mExecSync) {
+ if (this.mSyntaxHighlightProcessor != null) {
+ try {
+ this.mSyntaxHighlightProcessor.initialize();
+ this.mSyntaxHighlightProcessor.process(this.mEditor.getText());
+ } catch (Exception ex) {
+ // An error in a syntax library, should not break down app.
+ Log.e(TAG, "Syntax highlight failed.", ex); //$NON-NLS-1$
+ }
+ }
+ }
}
/**
@@ -524,6 +787,14 @@ public class EditorActivity extends Activity implements TextWatcher {
private void showOverflowPopUp(View anchor) {
SimpleMenuListAdapter adapter =
new HighlightedSimpleMenuListAdapter(this, R.menu.editor);
+ MenuItem noSuggestions = adapter.getMenu().findItem(R.id.mnu_no_suggestions);
+ if (noSuggestions != null) {
+ if (this.mBinary) {
+ adapter.getMenu().removeItem(R.id.mnu_no_suggestions);
+ } else {
+ noSuggestions.setChecked(this.mNoSuggestions);
+ }
+ }
MenuItem wordWrap = adapter.getMenu().findItem(R.id.mnu_word_wrap);
if (wordWrap != null) {
if (this.mBinary) {
@@ -532,6 +803,14 @@ public class EditorActivity extends Activity implements TextWatcher {
wordWrap.setChecked(this.mWordWrap);
}
}
+ MenuItem syntaxHighlight = adapter.getMenu().findItem(R.id.mnu_syntax_highlight);
+ if (syntaxHighlight != null) {
+ if (this.mBinary) {
+ adapter.getMenu().removeItem(R.id.mnu_syntax_highlight);
+ } else {
+ syntaxHighlight.setChecked(this.mSyntaxHighlight);
+ }
+ }
final ListPopupWindow popup =
DialogHelper.createListPopupWindow(this, adapter, anchor);
@@ -542,10 +821,15 @@ public class EditorActivity extends Activity implements TextWatcher {
final int position, final long id) {
final int itemId = (int)id;
switch (itemId) {
+ case R.id.mnu_no_suggestions:
+ toggleNoSuggestions();
+ break;
case R.id.mnu_word_wrap:
- popup.dismiss();
toggleWordWrap();
break;
+ case R.id.mnu_syntax_highlight:
+ toggleSyntaxHighlight();
+ break;
case R.id.mnu_settings:
//Settings
Intent settings = new Intent(EditorActivity.this, SettingsPreferences.class);
@@ -654,6 +938,14 @@ public class EditorActivity extends Activity implements TextWatcher {
return;
}
+ // Get the syntax highlight processor
+ SyntaxHighlightFactory shpFactory =
+ SyntaxHighlightFactory.getDefaultFactory(new ResourcesResolver());
+ this.mSyntaxHighlightProcessor = shpFactory.getSyntaxHighlightProcessor(f);
+ if (this.mSyntaxHighlightProcessor != null) {
+ this.mSyntaxHighlightProcessor.initialize();
+ }
+
// Check that we have read access
try {
FileHelper.ensureReadAccess(
@@ -710,6 +1002,8 @@ public class EditorActivity extends Activity implements TextWatcher {
@Override
protected Boolean doInBackground(FileSystemObject... params) {
+ final EditorActivity activity = EditorActivity.this;
+
// Only one argument (the file to open)
FileSystemObject fso = params[0];
this.mCause = null;
@@ -719,7 +1013,7 @@ public class EditorActivity extends Activity implements TextWatcher {
while (true) {
// Configure the reader
this.mReader = new AsyncReader();
- this.mReader.mFso = fso;
+ this.mReader.mReadFso = fso;
this.mReader.mListener = new OnProgressListener() {
@Override
@SuppressWarnings("synthetic-access")
@@ -729,8 +1023,7 @@ public class EditorActivity extends Activity implements TextWatcher {
};
// Execute the command (read the file)
- CommandHelper.read(
- EditorActivity.this, fso.getFullPath(), this.mReader, null);
+ CommandHelper.read(activity, fso.getFullPath(), this.mReader, null);
// Wait for
synchronized (this.mReader.mSync) {
@@ -749,26 +1042,31 @@ public class EditorActivity extends Activity implements TextWatcher {
}
// Now we have the byte array with all the data. is a binary file?
- // Then dump them byte array to hex dump string
- // Don't use the Hexdump helper class, so we can show the progress of
- // the dump process
- if (EditorActivity.this.mBinary) {
+ // Then dump them byte array to hex dump string (only if users settings
+ // to dump file)
+ boolean hexDump =
+ Preferences.getSharedPreferences().getBoolean(
+ FileManagerSettings.SETTINGS_EDITOR_HEXDUMP.getId(),
+ ((Boolean)FileManagerSettings.SETTINGS_EDITOR_HEXDUMP.
+ getDefaultValue()).booleanValue());
+ if (activity.mBinary && hexDump) {
+ // we do not use the Hexdump helper class, because we need to show the
+ // progress of the dump process
this.mReader.mBuffer =
- new StringBuilder(
+ new SpannableStringBuilder(
toHexPrintableString(
toHexDump(
this.mReader.mByteBuffer.toByteArray())));
} else {
this.mReader.mBuffer =
- new StringBuilder(
+ new SpannableStringBuilder(
new String(this.mReader.mByteBuffer.toByteArray()));
}
this.mReader.mByteBuffer = null;
- // 100% - We need two calls here to proper display the message
+ // 100%
this.changeToDisplaying = true;
publishProgress(new Integer(0));
- publishProgress(new Integer(0));
} catch (Exception e) {
this.mCause = e;
@@ -786,29 +1084,43 @@ public class EditorActivity extends Activity implements TextWatcher {
@Override
protected void onPostExecute(Boolean result) {
+ final EditorActivity activity = EditorActivity.this;
+
// Is error?
if (!result.booleanValue()) {
if (this.mCause != null) {
- ExceptionUtil.translateException(EditorActivity.this, this.mCause);
- EditorActivity.this.mEditor.setEnabled(false);
+ ExceptionUtil.translateException(activity, this.mCause);
+ activity.mEditor.setEnabled(false);
}
} else {
// Now we have the buffer, set the text of the editor
- if (EditorActivity.this.mBinary) {
- EditorActivity.this.mEditor.setText(
+ if (activity.mBinary) {
+ activity.mEditor.setText(
this.mReader.mBuffer, BufferType.NORMAL);
} else {
- EditorActivity.this.mEditor.setText(
+ activity.mEditor.setText(
this.mReader.mBuffer, BufferType.EDITABLE);
+
+ // Highlight editor text syntax
+ if (activity.mSyntaxHighlight &&
+ activity.mSyntaxHighlightProcessor != null) {
+ try {
+ activity.mSyntaxHighlightProcessor.process(
+ activity.mEditor.getText());
+ } catch (Exception ex) {
+ // An error in a syntax library, should not break down app.
+ Log.e(TAG, "Syntax highlight failed.", ex); //$NON-NLS-1$
+ }
+ }
}
this.mReader.mBuffer = null; //Cleanup
setDirty(false);
- EditorActivity.this.mEditor.setEnabled(!EditorActivity.this.mReadOnly);
+ activity.mEditor.setEnabled(!activity.mReadOnly);
// Notify read-only mode
- if (EditorActivity.this.mReadOnly) {
+ if (activity.mReadOnly) {
DialogHelper.showToast(
- EditorActivity.this,
+ activity,
R.string.editor_read_only_mode,
Toast.LENGTH_SHORT);
}
@@ -830,26 +1142,30 @@ public class EditorActivity extends Activity implements TextWatcher {
* @param progress The progress
*/
private void doProgress(boolean visible, int progress) {
+ final EditorActivity activity = EditorActivity.this;
+
// Show the progress bar
- EditorActivity.this.mProgressBar.setProgress(progress);
- EditorActivity.this.mProgress.setVisibility(
- visible ? View.VISIBLE : View.GONE);
+ activity.mProgressBar.setProgress(progress);
+ activity.mProgress.setVisibility(visible ? View.VISIBLE : View.GONE);
if (this.changeToBinaryMode) {
// Hexdump always in nowrap mode
- if (EditorActivity.this.mWordWrap) {
- EditorActivity.this.toggleWordWrap();
+ if (activity.mWordWrap) {
+ activity.toggleWordWrap();
+ }
+ // Hexdump always has no syntax highlight
+ if (activity.mSyntaxHighlight) {
+ activity.toggleSyntaxHighlight();
}
// Show hex dumping text
- EditorActivity.this.mProgressBarMsg.setText(R.string.dumping_message);
- EditorActivity.this.mEditor.setTextAppearance(
- EditorActivity.this, R.style.hexeditor_text_appearance);
- EditorActivity.this.mEditor.setTypeface(Typeface.MONOSPACE);
+ activity.mProgressBarMsg.setText(R.string.dumping_message);
+ activity.mEditor.setTextAppearance(activity, R.style.hexeditor_text_appearance);
+ activity.mEditor.setTypeface(Typeface.MONOSPACE);
this.changeToBinaryMode = false;
}
else if (this.changeToDisplaying) {
- EditorActivity.this.mProgressBarMsg.setText(R.string.displaying_message);
+ activity.mProgressBarMsg.setText(R.string.displaying_message);
this.changeToDisplaying = false;
}
}
@@ -1030,7 +1346,10 @@ public class EditorActivity extends Activity implements TextWatcher {
* {@inheritDoc}
*/
@Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {/**NON BLOCK**/}
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ this.mEditStart = start;
+ this.mEditEnd = start + count;
+ }
/**
* {@inheritDoc}
@@ -1038,6 +1357,9 @@ public class EditorActivity extends Activity implements TextWatcher {
@Override
public void afterTextChanged(Editable s) {
setDirty(true);
+ if (this.mSyntaxHighlightProcessor != null) {
+ this.mSyntaxHighlightProcessor.process(s, this.mEditStart, this.mEditEnd);
+ }
}
/**
@@ -1117,6 +1439,11 @@ public class EditorActivity extends Activity implements TextWatcher {
//- ProgressBar
Drawable dw = theme.getDrawable(this, "horizontal_progress_bar"); //$NON-NLS-1$
this.mProgressBar.setProgressDrawable(dw);
+
+ // Need a full process of syntax highlight
+ if (!this.mBinary && this.mSyntaxHighlight && this.mSyntaxHighlightProcessor != null) {
+ reloadSyntaxHighlight();
+ }
}
}
diff --git a/src/com/cyanogenmod/filemanager/activities/PickerActivity.java b/src/com/cyanogenmod/filemanager/activities/PickerActivity.java
index 3c8d179c..6c6b9961 100644
--- a/src/com/cyanogenmod/filemanager/activities/PickerActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/PickerActivity.java
@@ -425,7 +425,7 @@ public class PickerActivity extends Activity
}
}
- private boolean isFilePickIntent(Intent intent) {
+ private static boolean isFilePickIntent(Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_GET_CONTENT.equals(action)) {
@@ -441,7 +441,7 @@ public class PickerActivity extends Activity
return false;
}
- private boolean isDirectoryPickIntent(Intent intent) {
+ private static boolean isDirectoryPickIntent(Intent intent) {
if (Intent.ACTION_PICK.equals(intent.getAction()) && intent.getData() != null) {
String scheme = intent.getData().getScheme();
if (FOLDER_URI_SCHEME.equals(scheme) || DIRECTORY_URI_SCHEME.equals(scheme)) {
@@ -452,7 +452,7 @@ public class PickerActivity extends Activity
return false;
}
- private File getInitialDirectoryFromIntent(Intent intent) {
+ private static File getInitialDirectoryFromIntent(Intent intent) {
if (!Intent.ACTION_PICK.equals(intent.getAction())) {
return null;
}
@@ -478,7 +478,7 @@ public class PickerActivity extends Activity
return file.getParentFile();
}
- private Uri getResultUriForFileFromIntent(File src, Intent intent) {
+ private static Uri getResultUriForFileFromIntent(File src, Intent intent) {
Uri result = Uri.fromFile(src);
if (Intent.ACTION_PICK.equals(intent.getAction()) && intent.getData() != null) {
diff --git a/src/com/cyanogenmod/filemanager/activities/SearchActivity.java b/src/com/cyanogenmod/filemanager/activities/SearchActivity.java
index 60d043c8..75d528e4 100644
--- a/src/com/cyanogenmod/filemanager/activities/SearchActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/SearchActivity.java
@@ -48,8 +48,8 @@ import android.widget.Toast;
import com.cyanogenmod.filemanager.FileManagerApplication;
import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.activities.preferences.SearchPreferenceFragment;
import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
-import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences.SearchPreferenceFragment;
import com.cyanogenmod.filemanager.adapters.SearchResultAdapter;
import com.cyanogenmod.filemanager.commands.AsyncResultExecutable;
import com.cyanogenmod.filemanager.commands.AsyncResultListener;
diff --git a/src/com/cyanogenmod/filemanager/activities/preferences/EditorPreferenceFragment.java b/src/com/cyanogenmod/filemanager/activities/preferences/EditorPreferenceFragment.java
new file mode 100644
index 00000000..03836c56
--- /dev/null
+++ b/src/com/cyanogenmod/filemanager/activities/preferences/EditorPreferenceFragment.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2012 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.activities.preferences;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.util.Log;
+
+import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
+import com.cyanogenmod.filemanager.preferences.Preferences;
+
+/**
+ * A class that manages the editor options
+ */
+public class EditorPreferenceFragment extends TitlePreferenceFragment {
+
+ private static final String TAG = "EditorPreferenceFragment"; //$NON-NLS-1$
+
+ private static final boolean DEBUG = false;
+
+ private CheckBoxPreference mNoSuggestions;
+ private CheckBoxPreference mWordWrap;
+ private CheckBoxPreference mHexdump;
+
+ private CheckBoxPreference mSyntaxHighlight;
+
+
+ /**
+ * @hide
+ */
+ boolean mLoaded = false;
+
+ private final OnPreferenceChangeListener mOnChangeListener =
+ new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(final Preference preference, Object newValue) {
+ boolean ret = true;
+
+ String key = preference.getKey();
+ if (DEBUG) {
+ Log.d(TAG,
+ String.format("New value for %s: %s", //$NON-NLS-1$
+ key,
+ String.valueOf(newValue)));
+ }
+
+ // Notify the change (only if fragment is loaded. Default values are loaded
+ // while not in loaded mode)
+ if (EditorPreferenceFragment.this.mLoaded && ret) {
+ Intent intent = new Intent(FileManagerSettings.INTENT_SETTING_CHANGED);
+ intent.putExtra(
+ FileManagerSettings.EXTRA_SETTING_CHANGED_KEY, preference.getKey());
+ getActivity().sendBroadcast(intent);
+ }
+
+ return ret;
+ }
+ };
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Change the preference manager
+ getPreferenceManager().setSharedPreferencesName(Preferences.SETTINGS_FILENAME);
+ getPreferenceManager().setSharedPreferencesMode(Context.MODE_PRIVATE);
+ this.mLoaded = false;
+
+ // Add the preferences
+ addPreferencesFromResource(R.xml.preferences_editor);
+
+ // No suggestions
+ this.mNoSuggestions =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_EDITOR_NO_SUGGESTIONS.getId());
+ this.mNoSuggestions.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ // WordWrap
+ this.mWordWrap =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_EDITOR_WORD_WRAP.getId());
+ this.mWordWrap.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ // Hexdump
+ this.mHexdump =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_EDITOR_HEXDUMP.getId());
+ this.mHexdump.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ // Syntax highlight
+ this.mSyntaxHighlight =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_EDITOR_SYNTAX_HIGHLIGHT.getId());
+ this.mSyntaxHighlight.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ // Loaded
+ this.mLoaded = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public CharSequence getTitle() {
+ return getString(R.string.pref_editor);
+ }
+}
diff --git a/src/com/cyanogenmod/filemanager/activities/preferences/EditorSHColorSchemePreferenceFragment.java b/src/com/cyanogenmod/filemanager/activities/preferences/EditorSHColorSchemePreferenceFragment.java
new file mode 100644
index 00000000..4dbababd
--- /dev/null
+++ b/src/com/cyanogenmod/filemanager/activities/preferences/EditorSHColorSchemePreferenceFragment.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2012 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.activities.preferences;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.ash.HighlightColors;
+import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
+import com.cyanogenmod.filemanager.preferences.Preferences;
+import com.cyanogenmod.filemanager.ui.ThemeManager;
+import com.cyanogenmod.filemanager.ui.preferences.ColorPickerPreference;
+import com.cyanogenmod.filemanager.util.ExceptionUtil;
+
+/**
+ * A class that manages the color scheme of the syntax highlight processor.
+ */
+public class EditorSHColorSchemePreferenceFragment extends TitlePreferenceFragment {
+
+ private static final String TAG = "EditorSHColorSchemePreferenceFragment"; //$NON-NLS-1$
+
+ private static final boolean DEBUG = false;
+
+ private static final String KEY_RESET_COLOR_SCHEME = "ash_reset_color_scheme"; //$NON-NLS-1$
+
+ private CheckBoxPreference mUseThemeDefault;
+ private Preference mResetColorScheme;
+ private ColorPickerPreference[] mColorScheme;
+
+ /**
+ * @hide
+ */
+ boolean mLoaded = false;
+
+ private final OnPreferenceChangeListener mOnChangeListener =
+ new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(final Preference preference, final Object newValue) {
+ boolean ret = true;
+
+ String key = preference.getKey();
+ if (DEBUG) {
+ Log.d(TAG,
+ String.format("New value for %s: %s", //$NON-NLS-1$
+ key,
+ String.valueOf(newValue)));
+ }
+
+ // Use theme default
+ if (key.compareTo(
+ FileManagerSettings.SETTINGS_EDITOR_SH_USE_THEME_DEFAULT.getId()) == 0) {
+ boolean enabled = ((Boolean)newValue).booleanValue();
+ setColorSchemeEnabled(!enabled);
+
+ } else if (isColorSchemePreference(preference)) {
+ // Unify the color schemes property. Save the property here
+ int color = ((Integer)newValue).intValue();
+ try {
+ String colorScheme = toColorSchemeSet(preference, color);
+ Preferences.savePreference(
+ FileManagerSettings.SETTINGS_EDITOR_SH_COLOR_SCHEME,
+ colorScheme,
+ true);
+ } catch (Exception e) {
+ ExceptionUtil.translateException(getActivity(), e);
+ }
+ ((ColorPickerPreference)preference).setColor(color);
+
+ // Change the key to get notifications of color scheme
+ key = FileManagerSettings.SETTINGS_EDITOR_SH_COLOR_SCHEME.getId();
+ }
+
+ // Notify the change (only if fragment is loaded. Default values are loaded
+ // while not in loaded mode)
+ if (EditorSHColorSchemePreferenceFragment.this.mLoaded && ret) {
+ Intent intent = new Intent(FileManagerSettings.INTENT_SETTING_CHANGED);
+ intent.putExtra(
+ FileManagerSettings.EXTRA_SETTING_CHANGED_KEY, key);
+ getActivity().sendBroadcast(intent);
+ }
+
+ return ret;
+ }
+ };
+
+ private final OnPreferenceClickListener mOnClickListener =
+ new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ String key = preference.getKey();
+ if (KEY_RESET_COLOR_SCHEME.compareTo(key) == 0) {
+ loadDefaultColorScheme(true);
+ }
+ return false;
+ }
+ };
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Change the preference manager
+ getPreferenceManager().setSharedPreferencesName(Preferences.SETTINGS_FILENAME);
+ getPreferenceManager().setSharedPreferencesMode(Context.MODE_PRIVATE);
+
+ // Add the preferences
+ addPreferencesFromResource(R.xml.preferences_editor_color_scheme);
+
+ // Color scheme (need to resolver color scheme prior to use theme default)
+ loadDefaultColorScheme(false);
+
+ // Use Theme default
+ this.mUseThemeDefault =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_EDITOR_SH_USE_THEME_DEFAULT.getId());
+ Boolean defaultValue = ((Boolean)FileManagerSettings.
+ SETTINGS_EDITOR_SH_USE_THEME_DEFAULT.getDefaultValue());
+ Boolean value =
+ Boolean.valueOf(
+ Preferences.getSharedPreferences().getBoolean(
+ FileManagerSettings.SETTINGS_EDITOR_SH_USE_THEME_DEFAULT.getId(),
+ defaultValue.booleanValue()));
+
+ // Reset to default theme color scheme
+ this.mResetColorScheme = findPreference(KEY_RESET_COLOR_SCHEME);
+
+ // Now the listeners
+ this.mOnChangeListener.onPreferenceChange(this.mUseThemeDefault, value);
+ this.mUseThemeDefault.setOnPreferenceChangeListener(this.mOnChangeListener);
+ this.mResetColorScheme.setOnPreferenceClickListener(this.mOnClickListener);
+
+ // Loaded
+ this.mLoaded = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public CharSequence getTitle() {
+ return getString(R.string.pref_syntax_highlight_color_scheme);
+ }
+
+ /**
+ * Method that loads the default color scheme
+ *
+ * @param reset Whether the color scheme should be reseted
+ * @hide
+ */
+ void loadDefaultColorScheme(boolean reset) {
+ try {
+ String defaultValue =
+ (String)FileManagerSettings.SETTINGS_EDITOR_SH_COLOR_SCHEME.getDefaultValue();
+ if (!reset) {
+ defaultValue =
+ Preferences.getSharedPreferences().getString(
+ FileManagerSettings.SETTINGS_EDITOR_SH_COLOR_SCHEME.getId(),
+ defaultValue);
+ } else {
+ Preferences.savePreference(
+ FileManagerSettings.SETTINGS_EDITOR_SH_COLOR_SCHEME,
+ defaultValue,
+ true);
+ }
+ int[] colorScheme = toColorShemeArray(defaultValue);
+ HighlightColors[] colors = HighlightColors.values();
+ int cc = colors.length;
+ this.mColorScheme = new ColorPickerPreference[cc];
+ for (int i = 0; i < cc; i++) {
+ this.mColorScheme[i] = (ColorPickerPreference)findPreference(colors[i].getId());
+ setColorScheme(colors[i], colorScheme, i);
+ this.mColorScheme[i].setOnPreferenceChangeListener(this.mOnChangeListener);
+ }
+ } catch (Exception e) {
+ ExceptionUtil.translateException(getActivity(), e);
+ }
+ }
+
+ /**
+ * Method that set the enabled status of the color schemes preferences
+ *
+ * @param enable If the color scheme preferences should be enabled or not.
+ * @hide
+ */
+ void setColorSchemeEnabled(final boolean enable) {
+ int cc = this.mColorScheme.length;
+ for (int i = 0; i < cc; i++) {
+ this.mColorScheme[i].setEnabled(enable);
+ }
+ this.mResetColorScheme.setEnabled(enable);
+ }
+
+ /**
+ * Method that set a color scheme (use setting or theme default)
+ *
+ * @param color The color reference
+ * @param colorScheme The array of colors
+ * @param pos The position of the color
+ * @hide
+ */
+ void setColorScheme(HighlightColors color, int[] colorScheme, int pos) {
+ try {
+ this.mColorScheme[pos].setColor(colorScheme[pos]);
+ } catch (Exception e) {
+ this.mColorScheme[pos].setColor(
+ ThemeManager.getCurrentTheme(
+ getActivity()).getColor(getActivity(), color.getResId()));
+ Log.w(TAG,
+ String.format(
+ "Color scheme value not found for \"%s\"", //$NON-NLS-1$
+ color.getId()));
+ }
+ }
+
+ /**
+ * Method that returns if the preference is part of the color scheme preferences
+ *
+ * @return boolean Whether preference is part of the color scheme preferences
+ * @hide
+ */
+ static boolean isColorSchemePreference(final Preference preference) {
+ String key = preference.getKey();
+ if (key == null) {
+ return false;
+ }
+ HighlightColors[] colors = HighlightColors.values();
+ int cc = colors.length;
+ for (int i = 0; i < cc; i++) {
+ if (colors[i].getId().compareTo(key) == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Method that converts the string set of color schemes to an array of colors
+ *
+ * @param value The string set of color schemes to parse
+ * @return int[] Array of colors
+ */
+ public static int[] toColorShemeArray(String value) {
+ if (value == null || value.length() == 0) {
+ return new int[]{};
+ }
+ String[] values = value.split("\\|"); //$NON-NLS-1$
+ int[] colors = new int[values.length];
+ int cc = colors.length;
+ for (int i = 0; i < cc; i++) {
+ try {
+ colors[i] = Integer.parseInt(values[i]);
+ } catch (Exception e) {
+ Log.w(TAG,
+ String.format(
+ "Problem parsing color value \"%s\" on position %d", //$NON-NLS-1$
+ values[i], Integer.valueOf(i)));
+ colors[i] = 0;
+ }
+ }
+ return colors;
+ }
+
+ /**
+ * Method that converts all the color scheme preference to one unified preference set
+ *
+ * @param preference The color scheme preference that was changed
+ * @param newValue The new value of the color scheme
+ * @return colorScheme The actual color schemes
+ * @hide
+ */
+ String toColorSchemeSet(final Preference preference, final int newValue) {
+ int cc = this.mColorScheme.length;
+ String[] colorSchemes = new String[cc];
+ for (int i = 0; i < cc; i++) {
+ String prop = String.valueOf(this.mColorScheme[i].getColor());
+ if (this.mColorScheme[i].getKey().compareTo(preference.getKey()) == 0) {
+ prop = String.valueOf(newValue);
+ }
+ colorSchemes[i] = prop;
+ }
+ return TextUtils.join("|", colorSchemes); //$NON-NLS-1$
+ }
+}
diff --git a/src/com/cyanogenmod/filemanager/activities/preferences/GeneralPreferenceFragment.java b/src/com/cyanogenmod/filemanager/activities/preferences/GeneralPreferenceFragment.java
new file mode 100644
index 00000000..1e98105b
--- /dev/null
+++ b/src/com/cyanogenmod/filemanager/activities/preferences/GeneralPreferenceFragment.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2012 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.activities.preferences;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.util.Log;
+
+import com.cyanogenmod.filemanager.FileManagerApplication;
+import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.console.ConsoleBuilder;
+import com.cyanogenmod.filemanager.preferences.AccessMode;
+import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
+import com.cyanogenmod.filemanager.preferences.ObjectStringIdentifier;
+import com.cyanogenmod.filemanager.preferences.Preferences;
+
+/**
+ * A class that manages the commons options of the application
+ */
+public class GeneralPreferenceFragment extends TitlePreferenceFragment {
+
+ private static final String TAG = "GeneralPreferenceFragment"; //$NON-NLS-1$
+
+ private static final boolean DEBUG = false;
+
+ private CheckBoxPreference mCaseSensitiveSort;
+ private ListPreference mFreeDiskSpaceWarningLevel;
+ private CheckBoxPreference mComputeFolderStatistics;
+// private CheckBoxPreference mUseFlinger;
+ private ListPreference mAccessMode;
+ private CheckBoxPreference mDebugTraces;
+
+ /**
+ * @hide
+ */
+ boolean mLoaded = false;
+
+ private final OnPreferenceChangeListener mOnChangeListener =
+ new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(final Preference preference, Object newValue) {
+ boolean ret = true;
+
+ String key = preference.getKey();
+ if (DEBUG) {
+ Log.d(TAG,
+ String.format("New value for %s: %s", //$NON-NLS-1$
+ key,
+ String.valueOf(newValue)));
+ }
+
+ // Disk usage warning level
+ if (FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.
+ getId().compareTo(key) == 0) {
+ String value = (String)newValue;
+ preference.setSummary(
+ getResources().getString(
+ R.string.pref_disk_usage_warning_level_summary, value));
+ }
+
+ // Access mode
+ else if (FileManagerSettings.SETTINGS_ACCESS_MODE.getId().compareTo(key) == 0) {
+ Activity activity = GeneralPreferenceFragment.this.getActivity();
+
+ String value = (String)newValue;
+ AccessMode oldMode = FileManagerApplication.getAccessMode();
+ AccessMode newMode = AccessMode.fromId(value);
+ if (oldMode.compareTo(newMode) != 0) {
+ // The mode was changes. Change the console
+ if (newMode.compareTo(AccessMode.ROOT) == 0) {
+ if (!ConsoleBuilder.changeToPrivilegedConsole(
+ activity.getApplicationContext())) {
+ value = String.valueOf(oldMode.ordinal());
+ ret = false;
+ }
+ } else {
+ if (!ConsoleBuilder.changeToNonPrivilegedConsole(
+ activity.getApplicationContext())) {
+ value = String.valueOf(oldMode.ordinal());
+ ret = false;
+ }
+ }
+ }
+
+ int valueId = Integer.valueOf(value).intValue();
+ String[] summary = getResources().getStringArray(
+ R.array.access_mode_summaries);
+ preference.setSummary(summary[valueId]);
+ }
+
+ // Notify the change (only if fragment is loaded. Default values are loaded
+ // while not in loaded mode)
+ if (GeneralPreferenceFragment.this.mLoaded && ret) {
+ Intent intent = new Intent(FileManagerSettings.INTENT_SETTING_CHANGED);
+ intent.putExtra(
+ FileManagerSettings.EXTRA_SETTING_CHANGED_KEY, preference.getKey());
+ getActivity().sendBroadcast(intent);
+ }
+
+ return ret;
+ }
+ };
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Change the preference manager
+ getPreferenceManager().setSharedPreferencesName(Preferences.SETTINGS_FILENAME);
+ getPreferenceManager().setSharedPreferencesMode(Context.MODE_PRIVATE);
+
+ // Add the preferences
+ addPreferencesFromResource(R.xml.preferences_general);
+
+ // Case sensitive sort
+ this.mCaseSensitiveSort =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_CASE_SENSITIVE_SORT.getId());
+ this.mCaseSensitiveSort.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ //Disk usage warning level
+ this.mFreeDiskSpaceWarningLevel =
+ (ListPreference)findPreference(
+ FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId());
+ this.mFreeDiskSpaceWarningLevel.setOnPreferenceChangeListener(this.mOnChangeListener);
+ String defaultValue = ((String)FileManagerSettings.
+ SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
+ String value = Preferences.getSharedPreferences().getString(
+ FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
+ defaultValue);
+ this.mOnChangeListener.onPreferenceChange(this.mFreeDiskSpaceWarningLevel, value);
+
+ // Compute folder statistics
+ this.mComputeFolderStatistics =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_COMPUTE_FOLDER_STATISTICS.getId());
+ this.mComputeFolderStatistics.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ // Use flinger
+// this.mUseFlinger =
+// (CheckBoxPreference)findPreference(
+// FileManagerSettings.SETTINGS_USE_FLINGER.getId());
+// this.mUseFlinger.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ // Access mode
+ this.mAccessMode =
+ (ListPreference)findPreference(
+ FileManagerSettings.SETTINGS_ACCESS_MODE.getId());
+ this.mAccessMode.setOnPreferenceChangeListener(this.mOnChangeListener);
+ defaultValue = ((ObjectStringIdentifier)FileManagerSettings.
+ SETTINGS_ACCESS_MODE.getDefaultValue()).getId();
+ value = Preferences.getSharedPreferences().getString(
+ FileManagerSettings.SETTINGS_ACCESS_MODE.getId(),
+ defaultValue);
+ this.mOnChangeListener.onPreferenceChange(this.mAccessMode, value);
+ // If device is not rooted, this setting cannot be changed
+ this.mAccessMode.setEnabled(FileManagerApplication.isDeviceRooted());
+
+ // Capture Debug traces
+ this.mDebugTraces =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_SHOW_TRACES.getId());
+ this.mDebugTraces.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ // Loaded
+ this.mLoaded = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public CharSequence getTitle() {
+ return getString(R.string.pref_general);
+ }
+}
diff --git a/src/com/cyanogenmod/filemanager/activities/preferences/SearchPreferenceFragment.java b/src/com/cyanogenmod/filemanager/activities/preferences/SearchPreferenceFragment.java
new file mode 100644
index 00000000..d826f154
--- /dev/null
+++ b/src/com/cyanogenmod/filemanager/activities/preferences/SearchPreferenceFragment.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2012 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.activities.preferences;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.provider.SearchRecentSuggestions;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
+import com.cyanogenmod.filemanager.preferences.ObjectStringIdentifier;
+import com.cyanogenmod.filemanager.preferences.Preferences;
+import com.cyanogenmod.filemanager.providers.RecentSearchesContentProvider;
+import com.cyanogenmod.filemanager.util.DialogHelper;
+
+/**
+ * A class that manages the search options
+ */
+public class SearchPreferenceFragment extends TitlePreferenceFragment {
+
+ private static final String TAG = "SearchPreferenceFragment"; //$NON-NLS-1$
+
+ private static final boolean DEBUG = false;
+
+ // Internal keys
+ private static final String REMOVE_SEARCH_TERMS_KEY =
+ "cm_filemanager_remove_saved_search_terms"; //$NON-NLS-1$
+
+ private CheckBoxPreference mHighlightTerms;
+ private CheckBoxPreference mShowRelevanceWidget;
+ private ListPreference mSortSearchResultMode;
+ private CheckBoxPreference mSaveSearchTerms;
+ private Preference mRemoveSearchTerms;
+
+ /**
+ * @hide
+ */
+ boolean mLoaded = false;
+
+ private final OnPreferenceChangeListener mOnChangeListener =
+ new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String key = preference.getKey();
+ if (DEBUG) {
+ Log.d(TAG,
+ String.format("New value for %s: %s", //$NON-NLS-1$
+ key,
+ String.valueOf(newValue)));
+ }
+
+ // Saved search terms
+ if (preference.getKey().compareTo(
+ FileManagerSettings.SETTINGS_SAVE_SEARCH_TERMS.getId()) == 0) {
+ if (!((Boolean)newValue).booleanValue()) {
+ // Remove search terms if saved search terms
+ // is not active by the user
+ clearRecentSearchTerms();
+ }
+
+ // Sort search result mode
+ } else if (FileManagerSettings.SETTINGS_SORT_SEARCH_RESULTS_MODE.
+ getId().compareTo(key) == 0) {
+ int value = Integer.valueOf((String)newValue).intValue();
+ String[] summary = getResources().getStringArray(
+ R.array.sort_search_results_mode_labels);
+ preference.setSummary(summary[value]);
+ }
+
+ // Notify the change (only if fragment is loaded. Default values are loaded
+ // while not in loaded mode)
+ if (SearchPreferenceFragment.this.mLoaded) {
+ Intent intent = new Intent(FileManagerSettings.INTENT_SETTING_CHANGED);
+ intent.putExtra(
+ FileManagerSettings.EXTRA_SETTING_CHANGED_KEY, preference.getKey());
+ getActivity().sendBroadcast(intent);
+ }
+
+ return true;
+ }
+ };
+
+ private final OnPreferenceClickListener mOnClickListener =
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (preference.getKey().compareTo(REMOVE_SEARCH_TERMS_KEY) == 0) {
+ // Remove search terms
+ clearRecentSearchTerms();
+
+ // Advise the user
+ DialogHelper.showToast(
+ getActivity(),
+ getActivity().getString(R.string.pref_remove_saved_search_terms_msg),
+ Toast.LENGTH_SHORT);
+ }
+ return false;
+ }
+ };
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Change the preference manager
+ getPreferenceManager().setSharedPreferencesName(Preferences.SETTINGS_FILENAME);
+ getPreferenceManager().setSharedPreferencesMode(Context.MODE_PRIVATE);
+ this.mLoaded = false;
+
+ // Add the preferences
+ addPreferencesFromResource(R.xml.preferences_search);
+
+ // Highlight terms
+ this.mHighlightTerms =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_HIGHLIGHT_TERMS.getId());
+ this.mHighlightTerms.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ // Relevance widget
+ this.mShowRelevanceWidget =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_SHOW_RELEVANCE_WIDGET.getId());
+ this.mShowRelevanceWidget.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ // Sort search result mode
+ this.mSortSearchResultMode =
+ (ListPreference)findPreference(
+ FileManagerSettings.SETTINGS_SORT_SEARCH_RESULTS_MODE.getId());
+ this.mSortSearchResultMode.setOnPreferenceChangeListener(this.mOnChangeListener);
+ String defaultValue = ((ObjectStringIdentifier)FileManagerSettings.
+ SETTINGS_SORT_SEARCH_RESULTS_MODE.getDefaultValue()).getId();
+ String value = Preferences.getSharedPreferences().getString(
+ FileManagerSettings.SETTINGS_SORT_SEARCH_RESULTS_MODE.getId(),
+ defaultValue);
+ this.mOnChangeListener.onPreferenceChange(this.mSortSearchResultMode, value);
+
+ // Saved search terms
+ this.mSaveSearchTerms =
+ (CheckBoxPreference)findPreference(
+ FileManagerSettings.SETTINGS_SAVE_SEARCH_TERMS.getId());
+ this.mSaveSearchTerms.setOnPreferenceChangeListener(this.mOnChangeListener);
+
+ // Remove search terms
+ this.mRemoveSearchTerms = findPreference(REMOVE_SEARCH_TERMS_KEY);
+ this.mRemoveSearchTerms.setOnPreferenceClickListener(this.mOnClickListener);
+
+ // Loaded
+ this.mLoaded = true;
+ }
+
+ /**
+ * Method that removes the recent suggestions on search activity
+ * @hide
+ */
+ void clearRecentSearchTerms() {
+ SearchRecentSuggestions suggestions =
+ new SearchRecentSuggestions(getActivity(),
+ RecentSearchesContentProvider.AUTHORITY,
+ RecentSearchesContentProvider.MODE);
+ suggestions.clearHistory();
+ Preferences.setLastSearch(null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public CharSequence getTitle() {
+ return getString(R.string.pref_search);
+ }
+}
diff --git a/src/com/cyanogenmod/filemanager/activities/preferences/SettingsPreferences.java b/src/com/cyanogenmod/filemanager/activities/preferences/SettingsPreferences.java
index 1119756c..fd4bbe1e 100644
--- a/src/com/cyanogenmod/filemanager/activities/preferences/SettingsPreferences.java
+++ b/src/com/cyanogenmod/filemanager/activities/preferences/SettingsPreferences.java
@@ -17,39 +17,24 @@
package com.cyanogenmod.filemanager.activities.preferences;
import android.app.ActionBar;
-import android.app.Activity;
+import android.app.Fragment;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
-import android.preference.PreferenceFragment;
-import android.provider.SearchRecentSuggestions;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
-import android.widget.Toast;
-import com.cyanogenmod.filemanager.FileManagerApplication;
import com.cyanogenmod.filemanager.R;
import com.cyanogenmod.filemanager.activities.ChangeLogActivity;
-import com.cyanogenmod.filemanager.console.ConsoleBuilder;
-import com.cyanogenmod.filemanager.preferences.AccessMode;
import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
-import com.cyanogenmod.filemanager.preferences.ObjectStringIdentifier;
-import com.cyanogenmod.filemanager.preferences.Preferences;
-import com.cyanogenmod.filemanager.providers.RecentSearchesContentProvider;
import com.cyanogenmod.filemanager.ui.ThemeManager;
import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
-import com.cyanogenmod.filemanager.ui.preferences.ThemeSelectorPreference;
-import com.cyanogenmod.filemanager.util.DialogHelper;
+import com.cyanogenmod.filemanager.util.AndroidHelper;
import java.util.List;
@@ -62,6 +47,8 @@ public class SettingsPreferences extends PreferenceActivity {
private static final boolean DEBUG = false;
+ private TextView mTitle;
+
private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -127,9 +114,9 @@ public class SettingsPreferences extends PreferenceActivity {
ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME);
getActionBar().setDisplayHomeAsUpEnabled(true);
View customTitle = getLayoutInflater().inflate(R.layout.simple_customtitle, null, false);
- TextView title = (TextView)customTitle.findViewById(R.id.customtitle_title);
- title.setText(R.string.pref);
- title.setContentDescription(getString(R.string.pref));
+ this.mTitle = (TextView)customTitle.findViewById(R.id.customtitle_title);
+ this.mTitle.setText(R.string.pref);
+ this.mTitle.setContentDescription(getString(R.string.pref));
getActionBar().setCustomView(customTitle);
}
@@ -167,422 +154,15 @@ public class SettingsPreferences extends PreferenceActivity {
}
/**
- * A class that manages the commons options of the application
- */
- public static class GeneralPreferenceFragment extends PreferenceFragment {
-
- private CheckBoxPreference mCaseSensitiveSort;
- private ListPreference mFreeDiskSpaceWarningLevel;
- private CheckBoxPreference mComputeFolderStatistics;
-// private CheckBoxPreference mUseFlinger;
- private ListPreference mAccessMode;
- private CheckBoxPreference mDebugTraces;
-
- /**
- * @hide
- */
- boolean mLoaded = false;
-
- private final OnPreferenceChangeListener mOnChangeListener =
- new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(final Preference preference, Object newValue) {
- boolean ret = true;
-
- String key = preference.getKey();
- if (DEBUG) {
- Log.d(TAG,
- String.format("New value for %s: %s", //$NON-NLS-1$
- key,
- String.valueOf(newValue)));
- }
-
- // Disk usage warning level
- if (FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.
- getId().compareTo(key) == 0) {
- String value = (String)newValue;
- preference.setSummary(
- getResources().getString(
- R.string.pref_disk_usage_warning_level_summary, value));
- }
-
- // Access mode
- else if (FileManagerSettings.SETTINGS_ACCESS_MODE.getId().compareTo(key) == 0) {
- Activity activity = GeneralPreferenceFragment.this.getActivity();
-
- String value = (String)newValue;
- AccessMode oldMode = FileManagerApplication.getAccessMode();
- AccessMode newMode = AccessMode.fromId(value);
- if (oldMode.compareTo(newMode) != 0) {
- // The mode was changes. Change the console
- if (newMode.compareTo(AccessMode.ROOT) == 0) {
- if (!ConsoleBuilder.changeToPrivilegedConsole(
- activity.getApplicationContext())) {
- value = String.valueOf(oldMode.ordinal());
- ret = false;
- }
- } else {
- if (!ConsoleBuilder.changeToNonPrivilegedConsole(
- activity.getApplicationContext())) {
- value = String.valueOf(oldMode.ordinal());
- ret = false;
- }
- }
- }
-
- int valueId = Integer.valueOf(value).intValue();
- String[] summary = getResources().getStringArray(
- R.array.access_mode_summaries);
- preference.setSummary(summary[valueId]);
- }
-
- // Notify the change (only if fragment is loaded. Default values are loaded
- // while not in loaded mode)
- if (GeneralPreferenceFragment.this.mLoaded && ret) {
- Intent intent = new Intent(FileManagerSettings.INTENT_SETTING_CHANGED);
- intent.putExtra(
- FileManagerSettings.EXTRA_SETTING_CHANGED_KEY, preference.getKey());
- getActivity().sendBroadcast(intent);
- }
-
- return ret;
- }
- };
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Change the preference manager
- getPreferenceManager().setSharedPreferencesName(Preferences.SETTINGS_FILENAME);
- getPreferenceManager().setSharedPreferencesMode(MODE_PRIVATE);
-
- // Add the preferences
- addPreferencesFromResource(R.xml.preferences_general);
-
- // Case sensitive sort
- this.mCaseSensitiveSort =
- (CheckBoxPreference)findPreference(
- FileManagerSettings.SETTINGS_CASE_SENSITIVE_SORT.getId());
- this.mCaseSensitiveSort.setOnPreferenceChangeListener(this.mOnChangeListener);
-
- //Disk usage warning level
- this.mFreeDiskSpaceWarningLevel =
- (ListPreference)findPreference(
- FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId());
- this.mFreeDiskSpaceWarningLevel.setOnPreferenceChangeListener(this.mOnChangeListener);
- String defaultValue = ((String)FileManagerSettings.
- SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
- String value = Preferences.getSharedPreferences().getString(
- FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
- defaultValue);
- this.mOnChangeListener.onPreferenceChange(this.mFreeDiskSpaceWarningLevel, value);
-
- // Compute folder statistics
- this.mComputeFolderStatistics =
- (CheckBoxPreference)findPreference(
- FileManagerSettings.SETTINGS_COMPUTE_FOLDER_STATISTICS.getId());
- this.mComputeFolderStatistics.setOnPreferenceChangeListener(this.mOnChangeListener);
-
- // Use flinger
-// this.mUseFlinger =
-// (CheckBoxPreference)findPreference(
-// FileManagerSettings.SETTINGS_USE_FLINGER.getId());
-// this.mUseFlinger.setOnPreferenceChangeListener(this.mOnChangeListener);
-
- // Access mode
- this.mAccessMode =
- (ListPreference)findPreference(
- FileManagerSettings.SETTINGS_ACCESS_MODE.getId());
- this.mAccessMode.setOnPreferenceChangeListener(this.mOnChangeListener);
- defaultValue = ((ObjectStringIdentifier)FileManagerSettings.
- SETTINGS_ACCESS_MODE.getDefaultValue()).getId();
- value = Preferences.getSharedPreferences().getString(
- FileManagerSettings.SETTINGS_ACCESS_MODE.getId(),
- defaultValue);
- this.mOnChangeListener.onPreferenceChange(this.mAccessMode, value);
- // If device is not rooted, this setting cannot be changed
- this.mAccessMode.setEnabled(FileManagerApplication.isDeviceRooted());
-
- // Capture Debug traces
- this.mDebugTraces =
- (CheckBoxPreference)findPreference(
- FileManagerSettings.SETTINGS_SHOW_TRACES.getId());
- this.mDebugTraces.setOnPreferenceChangeListener(this.mOnChangeListener);
-
- // Loaded
- this.mLoaded = true;
- }
- }
-
- /**
- * A class that manages the search options
- */
- public static class SearchPreferenceFragment extends PreferenceFragment {
-
- // Internal keys
- private static final String REMOVE_SEARCH_TERMS_KEY =
- "cm_filemanager_remove_saved_search_terms"; //$NON-NLS-1$
-
- private CheckBoxPreference mHighlightTerms;
- private CheckBoxPreference mShowRelevanceWidget;
- private ListPreference mSortSearchResultMode;
- private CheckBoxPreference mSaveSearchTerms;
- private Preference mRemoveSearchTerms;
-
- /**
- * @hide
- */
- boolean mLoaded = false;
-
- private final OnPreferenceChangeListener mOnChangeListener =
- new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- String key = preference.getKey();
- if (DEBUG) {
- Log.d(TAG,
- String.format("New value for %s: %s", //$NON-NLS-1$
- key,
- String.valueOf(newValue)));
- }
-
- // Saved search terms
- if (preference.getKey().compareTo(
- FileManagerSettings.SETTINGS_SAVE_SEARCH_TERMS.getId()) == 0) {
- if (!((Boolean)newValue).booleanValue()) {
- // Remove search terms if saved search terms
- // is not active by the user
- clearRecentSearchTerms();
- }
-
- // Sort search result mode
- } else if (FileManagerSettings.SETTINGS_SORT_SEARCH_RESULTS_MODE.
- getId().compareTo(key) == 0) {
- int value = Integer.valueOf((String)newValue).intValue();
- String[] summary = getResources().getStringArray(
- R.array.sort_search_results_mode_labels);
- preference.setSummary(summary[value]);
- }
-
- // Notify the change (only if fragment is loaded. Default values are loaded
- // while not in loaded mode)
- if (SearchPreferenceFragment.this.mLoaded) {
- Intent intent = new Intent(FileManagerSettings.INTENT_SETTING_CHANGED);
- intent.putExtra(
- FileManagerSettings.EXTRA_SETTING_CHANGED_KEY, preference.getKey());
- getActivity().sendBroadcast(intent);
- }
-
- return true;
- }
- };
-
- private final OnPreferenceClickListener mOnClickListener =
- new Preference.OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- if (preference.getKey().compareTo(REMOVE_SEARCH_TERMS_KEY) == 0) {
- // Remove search terms
- clearRecentSearchTerms();
-
- // Advise the user
- DialogHelper.showToast(
- getActivity(),
- getActivity().getString(R.string.pref_remove_saved_search_terms_msg),
- Toast.LENGTH_SHORT);
- }
- return false;
- }
- };
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Change the preference manager
- getPreferenceManager().setSharedPreferencesName(Preferences.SETTINGS_FILENAME);
- getPreferenceManager().setSharedPreferencesMode(MODE_PRIVATE);
- this.mLoaded = false;
-
- // Add the preferences
- addPreferencesFromResource(R.xml.preferences_search);
-
- // Highlight terms
- this.mHighlightTerms =
- (CheckBoxPreference)findPreference(
- FileManagerSettings.SETTINGS_HIGHLIGHT_TERMS.getId());
- this.mHighlightTerms.setOnPreferenceChangeListener(this.mOnChangeListener);
-
- // Relevance widget
- this.mShowRelevanceWidget =
- (CheckBoxPreference)findPreference(
- FileManagerSettings.SETTINGS_SHOW_RELEVANCE_WIDGET.getId());
- this.mShowRelevanceWidget.setOnPreferenceChangeListener(this.mOnChangeListener);
-
- // Sort search result mode
- this.mSortSearchResultMode =
- (ListPreference)findPreference(
- FileManagerSettings.SETTINGS_SORT_SEARCH_RESULTS_MODE.getId());
- this.mSortSearchResultMode.setOnPreferenceChangeListener(this.mOnChangeListener);
- String defaultValue = ((ObjectStringIdentifier)FileManagerSettings.
- SETTINGS_SORT_SEARCH_RESULTS_MODE.getDefaultValue()).getId();
- String value = Preferences.getSharedPreferences().getString(
- FileManagerSettings.SETTINGS_SORT_SEARCH_RESULTS_MODE.getId(),
- defaultValue);
- this.mOnChangeListener.onPreferenceChange(this.mSortSearchResultMode, value);
-
- // Saved search terms
- this.mSaveSearchTerms =
- (CheckBoxPreference)findPreference(
- FileManagerSettings.SETTINGS_SAVE_SEARCH_TERMS.getId());
- this.mSaveSearchTerms.setOnPreferenceChangeListener(this.mOnChangeListener);
-
- // Remove search terms
- this.mRemoveSearchTerms = findPreference(REMOVE_SEARCH_TERMS_KEY);
- this.mRemoveSearchTerms.setOnPreferenceClickListener(this.mOnClickListener);
-
- // Loaded
- this.mLoaded = true;
- }
-
- /**
- * Method that removes the recent suggestions on search activity
- * @hide
- */
- void clearRecentSearchTerms() {
- SearchRecentSuggestions suggestions =
- new SearchRecentSuggestions(getActivity(),
- RecentSearchesContentProvider.AUTHORITY,
- RecentSearchesContentProvider.MODE);
- suggestions.clearHistory();
- Preferences.setLastSearch(null);
- }
- }
-
- /**
- * A class that manages the editor options
- */
- public static class EditorPreferenceFragment extends PreferenceFragment {
-
- private CheckBoxPreference mWordWrap;
-
- /**
- * @hide
- */
- boolean mLoaded = false;
-
- private final OnPreferenceChangeListener mOnChangeListener =
- new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(final Preference preference, Object newValue) {
- boolean ret = true;
-
- String key = preference.getKey();
- if (DEBUG) {
- Log.d(TAG,
- String.format("New value for %s: %s", //$NON-NLS-1$
- key,
- String.valueOf(newValue)));
- }
-
- // Notify the change (only if fragment is loaded. Default values are loaded
- // while not in loaded mode)
- if (EditorPreferenceFragment.this.mLoaded && ret) {
- Intent intent = new Intent(FileManagerSettings.INTENT_SETTING_CHANGED);
- intent.putExtra(
- FileManagerSettings.EXTRA_SETTING_CHANGED_KEY, preference.getKey());
- getActivity().sendBroadcast(intent);
- }
-
- return ret;
- }
- };
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Change the preference manager
- getPreferenceManager().setSharedPreferencesName(Preferences.SETTINGS_FILENAME);
- getPreferenceManager().setSharedPreferencesMode(MODE_PRIVATE);
- this.mLoaded = false;
-
- // Add the preferences
- addPreferencesFromResource(R.xml.preferences_editor);
-
- // WordWrap
- this.mWordWrap =
- (CheckBoxPreference)findPreference(
- FileManagerSettings.SETTINGS_EDITOR_WORD_WRAP.getId());
- this.mWordWrap.setOnPreferenceChangeListener(this.mOnChangeListener);
-
- // Loaded
- this.mLoaded = true;
- }
- }
-
- /**
- * A class that manages the theme selection
+ * {@inheritDoc}
*/
- public static class ThemesPreferenceFragment extends PreferenceFragment {
-
- private ThemeSelectorPreference mThemeSelector;
-
- private final OnPreferenceChangeListener mOnChangeListener =
- new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- String key = preference.getKey();
- if (DEBUG) {
- Log.d(TAG,
- String.format("New value for %s: %s", //$NON-NLS-1$
- key,
- String.valueOf(newValue)));
- }
-
- // Notify to all activities that the theme has changed
- Intent intent = new Intent(FileManagerSettings.INTENT_THEME_CHANGED);
- intent.putExtra(FileManagerSettings.EXTRA_THEME_ID, (String)newValue);
- getActivity().sendBroadcast(intent);
-
- //Wait for allow activities to apply the theme, prior to finish settings
- try {
- Thread.sleep(250L);
- } catch (Throwable e) {/**NON BLOCK**/}
- getActivity().finish();
- return true;
- }
- };
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Change the preference manager
- getPreferenceManager().setSharedPreferencesName(Preferences.SETTINGS_FILENAME);
- getPreferenceManager().setSharedPreferencesMode(MODE_PRIVATE);
-
- // Add the preferences
- addPreferencesFromResource(R.xml.preferences_themes);
-
- // Theme selector
- this.mThemeSelector =
- (ThemeSelectorPreference)findPreference(
- FileManagerSettings.SETTINGS_THEME.getId());
- this.mThemeSelector.setOnPreferenceChangeListener(this.mOnChangeListener);
+ @Override
+ public void onAttachFragment(Fragment fragment) {
+ super.onAttachFragment(fragment);
+ if (!AndroidHelper.isTablet(this) && fragment instanceof TitlePreferenceFragment) {
+ this.mTitle.setText(((TitlePreferenceFragment)fragment).getTitle());
+ } else {
+ this.mTitle.setText(R.string.pref);
}
}
diff --git a/src/com/cyanogenmod/filemanager/activities/preferences/ThemesPreferenceFragment.java b/src/com/cyanogenmod/filemanager/activities/preferences/ThemesPreferenceFragment.java
new file mode 100644
index 00000000..ad0a99fc
--- /dev/null
+++ b/src/com/cyanogenmod/filemanager/activities/preferences/ThemesPreferenceFragment.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 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.activities.preferences;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.util.Log;
+
+import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
+import com.cyanogenmod.filemanager.preferences.Preferences;
+import com.cyanogenmod.filemanager.ui.preferences.ThemeSelectorPreference;
+
+/**
+ * A class that manages the theme selection
+ */
+public class ThemesPreferenceFragment extends TitlePreferenceFragment {
+
+ private static final String TAG = "ThemesPreferenceFragment"; //$NON-NLS-1$
+
+ private static final boolean DEBUG = false;
+
+ private ThemeSelectorPreference mThemeSelector;
+
+ private final OnPreferenceChangeListener mOnChangeListener =
+ new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String key = preference.getKey();
+ if (DEBUG) {
+ Log.d(TAG,
+ String.format("New value for %s: %s", //$NON-NLS-1$
+ key,
+ String.valueOf(newValue)));
+ }
+
+ // Notify to all activities that the theme has changed
+ Intent intent = new Intent(FileManagerSettings.INTENT_THEME_CHANGED);
+ intent.putExtra(FileManagerSettings.EXTRA_THEME_ID, (String)newValue);
+ getActivity().sendBroadcast(intent);
+
+ //Wait for allow activities to apply the theme, prior to finish settings
+ try {
+ Thread.sleep(250L);
+ } catch (Throwable e) {/**NON BLOCK**/}
+ getActivity().finish();
+ return true;
+ }
+ };
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Change the preference manager
+ getPreferenceManager().setSharedPreferencesName(Preferences.SETTINGS_FILENAME);
+ getPreferenceManager().setSharedPreferencesMode(Context.MODE_PRIVATE);
+
+ // Add the preferences
+ addPreferencesFromResource(R.xml.preferences_themes);
+
+ // Theme selector
+ this.mThemeSelector =
+ (ThemeSelectorPreference)findPreference(
+ FileManagerSettings.SETTINGS_THEME.getId());
+ this.mThemeSelector.setOnPreferenceChangeListener(this.mOnChangeListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public CharSequence getTitle() {
+ return getString(R.string.pref_themes);
+ }
+}
diff --git a/src/com/cyanogenmod/filemanager/activities/preferences/TitlePreferenceFragment.java b/src/com/cyanogenmod/filemanager/activities/preferences/TitlePreferenceFragment.java
new file mode 100644
index 00000000..e835dea1
--- /dev/null
+++ b/src/com/cyanogenmod/filemanager/activities/preferences/TitlePreferenceFragment.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 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.activities.preferences;
+
+import android.preference.PreferenceFragment;
+
+/**
+ * The base class of all preference fragments of the filemanager app
+ */
+public abstract class TitlePreferenceFragment extends PreferenceFragment {
+ /**
+ * Method that returns the title of the preference fragment
+ *
+ * @return CharSequence The title of the fragment
+ */
+ public abstract CharSequence getTitle();
+}
diff --git a/src/com/cyanogenmod/filemanager/preferences/FileManagerSettings.java b/src/com/cyanogenmod/filemanager/preferences/FileManagerSettings.java
index c1818aee..6f66190d 100644
--- a/src/com/cyanogenmod/filemanager/preferences/FileManagerSettings.java
+++ b/src/com/cyanogenmod/filemanager/preferences/FileManagerSettings.java
@@ -130,12 +130,46 @@ public enum FileManagerSettings {
SETTINGS_SHOW_TRACES("cm_filemanager_show_debug_traces", Boolean.FALSE), //$NON-NLS-1$
/**
+ * When to editor should display suggestions
+ * @hide
+ */
+ SETTINGS_EDITOR_NO_SUGGESTIONS(
+ "cm_filemanager_editor_no_suggestions", Boolean.FALSE), //$NON-NLS-1$
+
+ /**
* When to editor should use word wrap
* @hide
*/
SETTINGS_EDITOR_WORD_WRAP("cm_filemanager_editor_word_wrap", Boolean.TRUE), //$NON-NLS-1$
/**
+ * When to editor should open a binary file in a hex viewer
+ * @hide
+ */
+ SETTINGS_EDITOR_HEXDUMP("cm_filemanager_editor_hexdump", Boolean.TRUE), //$NON-NLS-1$
+
+ /**
+ * When to editor should use the syntax highlight
+ * @hide
+ */
+ SETTINGS_EDITOR_SYNTAX_HIGHLIGHT(
+ "cm_filemanager_editor_syntax_highlight", Boolean.TRUE), //$NON-NLS-1$
+
+ /**
+ * When to editor should use the default color scheme of the theme for syntax highlight
+ * @hide
+ */
+ SETTINGS_EDITOR_SH_USE_THEME_DEFAULT(
+ "cm_filemanager_editor_sh_use_theme_default", Boolean.TRUE), //$NON-NLS-1$
+
+ /**
+ * When to editor should use the default color scheme of the theme for syntax highlight
+ * @hide
+ */
+ SETTINGS_EDITOR_SH_COLOR_SCHEME(
+ "cm_filemanager_editor_sh_color_scheme", ""), //$NON-NLS-1$ //$NON-NLS-2$
+
+ /**
* The current theme to use in the app
* @hide
*/
diff --git a/src/com/cyanogenmod/filemanager/preferences/Preferences.java b/src/com/cyanogenmod/filemanager/preferences/Preferences.java
index bbd218ae..171c63d4 100644
--- a/src/com/cyanogenmod/filemanager/preferences/Preferences.java
+++ b/src/com/cyanogenmod/filemanager/preferences/Preferences.java
@@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* A helper class for access and manage the preferences of the application.
@@ -168,6 +169,7 @@ public final class Preferences {
* @throws InvalidClassException If the value of a preference is not of the
* type of the preference
*/
+ @SuppressWarnings("unchecked")
private static void savePreferences(
Map<FileManagerSettings, Object> prefs, boolean noSaveIfExists, boolean applied)
throws InvalidClassException {
@@ -190,6 +192,8 @@ public final class Preferences {
editor.putBoolean(pref.getId(), ((Boolean)value).booleanValue());
} else if (value instanceof String && pref.getDefaultValue() instanceof String) {
editor.putString(pref.getId(), (String)value);
+ } else if (value instanceof Set && pref.getDefaultValue() instanceof Set) {
+ editor.putStringSet(pref.getId(), (Set<String>)value);
} else if (value instanceof ObjectIdentifier
&& pref.getDefaultValue() instanceof ObjectIdentifier) {
editor.putInt(pref.getId(), ((ObjectIdentifier)value).getId());
diff --git a/src/com/cyanogenmod/filemanager/ui/preferences/ColorPickerPreference.java b/src/com/cyanogenmod/filemanager/ui/preferences/ColorPickerPreference.java
new file mode 100644
index 00000000..22b5b261
--- /dev/null
+++ b/src/com/cyanogenmod/filemanager/ui/preferences/ColorPickerPreference.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2012 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.ui.preferences;
+
+import afzkl.development.mColorPicker.views.ColorDialogView;
+import afzkl.development.mColorPicker.views.ColorPanelView;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.SharedPreferences;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.cyanogenmod.filemanager.R;
+
+/**
+ * A {@link Preference} that allow to select/pick a color in a new window dialog.
+ */
+public class ColorPickerPreference extends DialogPreference {
+
+ private ColorPanelView mColorPicker;
+ private int mColor;
+
+ private ColorDialogView mColorDlg;
+
+ /**
+ * Constructor of <code>ColorPickerPreference</code>
+ *
+ * @param context The current context
+ */
+ public ColorPickerPreference(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Constructor of <code>ColorPickerPreference</code>
+ *
+ * @param context The current context
+ * @param attrs The attributes of the XML tag that is inflating the preference.
+ */
+ public ColorPickerPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setWidgetLayoutResource(R.layout.color_picker_pref_item);
+ }
+
+ /**
+ * Returns the color of the picker.
+ *
+ * @return The color of the picker.
+ */
+ public int getColor() {
+ return this.mColor;
+ }
+
+ /**
+ * Sets the color of the picker and saves it to the {@link SharedPreferences}.
+ *
+ * @param color The new color.
+ */
+ public void setColor(int color) {
+ // Always persist/notify the first time; don't assume the field's default of false.
+ final boolean changed = this.mColor != color;
+ if (changed) {
+ this.mColor = color;
+ // when called from onSetInitialValue the view is still not set
+ if (this.mColorPicker != null) {
+ this.mColorPicker.setColor(color);
+ }
+ persistInt(color);
+ if (changed) {
+ notifyDependencyChange(shouldDisableDependents());
+ notifyChanged();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ return Integer.valueOf(a.getColor(index, 0));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setColor(restoreValue ? getPersistedInt(0) : ((Integer)defaultValue).intValue());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onPrepareDialogBuilder(Builder builder) {
+ super.onPrepareDialogBuilder(builder);
+
+ // Configure the dialog
+ this.mColorDlg = new ColorDialogView(getContext());
+ this.mColorDlg.setColor(this.mColor);
+ this.mColorDlg.showAlphaSlider(true);
+ this.mColorDlg.setAlphaSliderText(
+ getContext().getString(R.string.color_picker_alpha_slider_text));
+ this.mColorDlg.setCurrentColorText(
+ getContext().getString(R.string.color_picker_current_text));
+ this.mColorDlg.setNewColorText(
+ getContext().getString(R.string.color_picker_new_text));
+ this.mColorDlg.setColorLabelText(
+ getContext().getString(R.string.color_picker_color));
+ builder.setView(this.mColorDlg);
+
+ // The color is selected by the user and confirmed by clicking ok
+ builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public void onClick(DialogInterface dialog, int which) {
+ int color = ColorPickerPreference.this.mColorDlg.getColor();
+ if (callChangeListener(Integer.valueOf(color))) {
+ setColor(color);
+ }
+ dialog.dismiss();
+ }
+ });
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ View v = view.findViewById(R.id.color_picker);
+ if (v != null && v instanceof ColorPanelView) {
+ this.mColorPicker = (ColorPanelView)v;
+ this.mColorPicker.setColor(this.mColor);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ if (isPersistent()) {
+ // No need to save instance state since it's persistent
+ return superState;
+ }
+
+ final SavedState myState = new SavedState(superState);
+ myState.color = getColor();
+ return myState;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state == null || !state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ setColor(myState.color);
+ }
+
+ /**
+ * A class for managing the instance state of a {@link ColorPickerPreference}.
+ */
+ static class SavedState extends BaseSavedState {
+ int color;
+
+ /**
+ * Constructor of <code>SavedState</code>
+ *
+ * @param source The source
+ */
+ public SavedState(Parcel source) {
+ super(source);
+ this.color = source.readInt();
+ }
+
+ /**
+ * Constructor of <code>SavedState</code>
+ *
+ * @param superState The parcelable state
+ */
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(this.color);
+ }
+
+ /**
+ * A class that generates instances of the <code>SavedState</code> class from a Parcel.
+ */
+ @SuppressWarnings("hiding")
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+}
diff --git a/src/com/cyanogenmod/filemanager/ui/widgets/InlineAutocompleteTextView.java b/src/com/cyanogenmod/filemanager/ui/widgets/InlineAutocompleteTextView.java
index 308be39f..1613f8a8 100644
--- a/src/com/cyanogenmod/filemanager/ui/widgets/InlineAutocompleteTextView.java
+++ b/src/com/cyanogenmod/filemanager/ui/widgets/InlineAutocompleteTextView.java
@@ -385,7 +385,7 @@ public class InlineAutocompleteTextView extends RelativeLayout
private static List<String> filter(List<String> data, String current) {
List<String> filter = new ArrayList<String>(data);
int size = filter.size();
- for (int i=size-1; i>=0; i--) {
+ for (int i = size-1; i >= 0; i--) {
String s = filter.get(i);
if (!s.startsWith(current)) {
filter.remove(i);
diff --git a/src/com/cyanogenmod/filemanager/ui/widgets/NavigationView.java b/src/com/cyanogenmod/filemanager/ui/widgets/NavigationView.java
index 9695760d..11570b43 100644
--- a/src/com/cyanogenmod/filemanager/ui/widgets/NavigationView.java
+++ b/src/com/cyanogenmod/filemanager/ui/widgets/NavigationView.java
@@ -870,7 +870,7 @@ public class NavigationView extends RelativeLayout implements
@Override
@SuppressWarnings("unqualified-field-access")
protected void onPostExecute(Boolean result) {
- if (!result.booleanValue()){
+ if (!result.booleanValue()) {
return;
}
onPostExecuteTask(
diff --git a/src/com/cyanogenmod/filemanager/util/CommandHelper.java b/src/com/cyanogenmod/filemanager/util/CommandHelper.java
index e6620601..8dddbcba 100644
--- a/src/com/cyanogenmod/filemanager/util/CommandHelper.java
+++ b/src/com/cyanogenmod/filemanager/util/CommandHelper.java
@@ -1297,7 +1297,7 @@ public final class CommandHelper {
newCreator().
createDeleteFileExecutable(compressOutFile);
writableExecute(context, executable3, c, true);
- if(executable3.getResult().booleanValue()){
+ if (executable3.getResult().booleanValue()) {
//- Compress
execute(context, executable1, c);
return executable1;
diff --git a/src/com/cyanogenmod/filemanager/util/FileHelper.java b/src/com/cyanogenmod/filemanager/util/FileHelper.java
index d1515047..45c8acb5 100644
--- a/src/com/cyanogenmod/filemanager/util/FileHelper.java
+++ b/src/com/cyanogenmod/filemanager/util/FileHelper.java
@@ -1126,22 +1126,22 @@ public final class FileHelper {
throw new InsufficientPermissionsException(executable);
}
// Check others
- if (permissions.getOthers().isRead() ){
+ if (permissions.getOthers().isRead()) {
return;
}
// Check user
- if (user.getId() == identity.getUser().getId() && permissions.getUser().isRead() ){
+ if (user.getId() == identity.getUser().getId() && permissions.getUser().isRead()) {
return;
}
// Check group
- if (group.getId() == identity.getGroup().getId() && permissions.getGroup().isRead() ){
+ if (group.getId() == identity.getGroup().getId() && permissions.getGroup().isRead()) {
return;
}
// Check groups
int cc = groups.size();
for (int i = 0; i < cc; i++) {
Group g = groups.get(i);
- if (group.getId() == g.getId() && permissions.getGroup().isRead() ){
+ if (group.getId() == g.getId() && permissions.getGroup().isRead()) {
return;
}
}
@@ -1181,22 +1181,22 @@ public final class FileHelper {
throw new InsufficientPermissionsException(executable);
}
// Check others
- if (permissions.getOthers().isWrite() ){
+ if (permissions.getOthers().isWrite()) {
return;
}
// Check user
- if (user.getId() == identity.getUser().getId() && permissions.getUser().isWrite() ){
+ if (user.getId() == identity.getUser().getId() && permissions.getUser().isWrite()) {
return;
}
// Check group
- if (group.getId() == identity.getGroup().getId() && permissions.getGroup().isWrite() ){
+ if (group.getId() == identity.getGroup().getId() && permissions.getGroup().isWrite()) {
return;
}
// Check groups
int cc = groups.size();
for (int i = 0; i < cc; i++) {
Group g = groups.get(i);
- if (group.getId() == g.getId() && permissions.getGroup().isWrite() ){
+ if (group.getId() == g.getId() && permissions.getGroup().isWrite()) {
return;
}
}
@@ -1236,22 +1236,22 @@ public final class FileHelper {
throw new InsufficientPermissionsException(executable);
}
// Check others
- if (permissions.getOthers().isExecute() ){
+ if (permissions.getOthers().isExecute()) {
return;
}
// Check user
- if (user.getId() == identity.getUser().getId() && permissions.getUser().isExecute() ){
+ if (user.getId() == identity.getUser().getId() && permissions.getUser().isExecute()) {
return;
}
// Check group
- if (group.getId() == identity.getGroup().getId() && permissions.getGroup().isExecute() ){
+ if (group.getId() == identity.getGroup().getId() && permissions.getGroup().isExecute()) {
return;
}
// Check groups
int cc = groups.size();
for (int i = 0; i < cc; i++) {
Group g = groups.get(i);
- if (group.getId() == g.getId() && permissions.getGroup().isExecute() ){
+ if (group.getId() == g.getId() && permissions.getGroup().isExecute()) {
return;
}
}
diff --git a/themes/res/values/dark_theme.xml b/themes/res/values/dark_theme.xml
index 70681dfe..1360509b 100644
--- a/themes/res/values/dark_theme.xml
+++ b/themes/res/values/dark_theme.xml
@@ -19,11 +19,6 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- The dark theme name -->
- <string name="dark_theme_name">Dark Theme</string>
- <!-- The dark theme description -->
- <string name="dark_theme_desc">A dark theme for CyanogenMod File Manager.</string>
-
<!-- The base theme used to customize some (non-themeables) widgets like dialogs
2 possibles values:
* holo: @android:style/Theme.Holo
@@ -174,4 +169,14 @@
<drawable name="dark_fso_type_text_drawable">@null</drawable>
<drawable name="dark_fso_type_video_drawable">@null</drawable> -->
+
+ <!-- Syntax Highlight -->
+ <color name="dark_ash_text_color">#99ffffff</color>
+ <color name="dark_ash_assignment_color">#99ffffff</color>
+ <color name="dark_ash_singleline_comment_color">#ff3f7f5f</color>
+ <color name="dark_ash_multiline_comment_color">#ff7f9fbf</color>
+ <color name="dark_ash_keyword_color">#ffd2568a</color>
+ <color name="dark_ash_quoted_string_color">#ff4Ab3b6</color>
+ <color name="dark_ash_variable_color">#ff91bcf8</color>
+
</resources>
diff --git a/themes/res/values/strings.xml b/themes/res/values/strings.xml
new file mode 100644
index 00000000..c28cd5ba
--- /dev/null
+++ b/themes/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+ -->
+
+<resources>
+
+ <!-- The dark theme strings -->
+ <string name="dark_theme_name">Dark Theme</string>
+ <string name="dark_theme_desc">A dark theme for CyanogenMod File Manager.</string>
+
+</resources>