aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-03-08 01:49:22 +0100
committerVincent Breitmoser <valodim@mugenguild.com>2015-03-08 01:49:22 +0100
commit2b5023a75d0c98738ed1aea2ea89de007cf2e3d7 (patch)
tree8617aa8dcad7e32c9cb5b8483534d888aaf0c7d0 /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget
parent581cad5b3f7b54fae652e2598b4e760eb19678d2 (diff)
parent4f11fb5a2f08ecf5fb81c86d590d04387cd1cd9a (diff)
downloadopen-keychain-2b5023a75d0c98738ed1aea2ea89de007cf2e3d7.tar.gz
open-keychain-2b5023a75d0c98738ed1aea2ea89de007cf2e3d7.tar.bz2
open-keychain-2b5023a75d0c98738ed1aea2ea89de007cf2e3d7.zip
Merge branch 'development' into linked-identities
Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java97
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java101
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java117
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java360
4 files changed, 675 insertions, 0 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
new file mode 100644
index 000000000..697f5a61e
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.widget;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.util.Patterns;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.ContactHelper;
+
+import java.util.regex.Matcher;
+
+public class EmailEditText extends AutoCompleteTextView {
+ EmailEditText emailEditText;
+
+ public EmailEditText(Context context) {
+ super(context);
+ emailEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ public EmailEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ emailEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ public EmailEditText(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ emailEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public EmailEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ emailEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ TextWatcher textWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ String email = editable.toString();
+ if (email.length() > 0) {
+ Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email);
+ if (emailMatcher.matches()) {
+ emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.uid_mail_ok, 0);
+ } else {
+ emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.uid_mail_bad, 0);
+ }
+ } else {
+ // remove drawable if email is empty
+ emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
+ }
+ }
+ };
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java
new file mode 100644
index 000000000..04c48922b
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.widget;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.widget.EditText;
+
+import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthView;
+
+/**
+ * Developer: chipset
+ * Package : org.sufficientlysecure.keychain.layouts
+ * Project : open-keychain
+ * Date : 6/3/15
+ */
+public class PasswordEditText extends EditText {
+
+ PasswordEditText passwordEditText;
+ PasswordStrengthView passwordStrengthView;
+
+ public PasswordEditText(Context context) {
+ super(context);
+ passwordEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ public PasswordEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ passwordEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ passwordEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ passwordEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ this.addTextChangedListener(textWatcher);
+ }
+
+
+ TextWatcher textWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ String passphrase = editable.toString();
+ passwordStrengthView.setPassword(passphrase);
+ }
+ };
+
+// public PasswordStrengthView getPasswordStrengthView() {
+// return passwordStrengthView;
+// }
+
+ public void setPasswordStrengthView(PasswordStrengthView mPasswordStrengthView) {
+ this.passwordStrengthView = mPasswordStrengthView;
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java
new file mode 100644
index 000000000..9e06c4cce
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java
@@ -0,0 +1,117 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Matt Allen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.util.AttributeSet;
+
+/**
+ * Created by matt on 04/07/2014.
+ * https://github.com/matt-allen/android-password-strength-indicator
+ */
+public class PasswordStrengthBarView extends PasswordStrengthView {
+
+ public PasswordStrengthBarView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mMinHeight = 80;
+ mMinWidth = 300;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ generateIndicatorColor();
+ // Default to full width
+ int indWidth = mIndicatorWidth;
+ // If score, leave it as full - can cause it to become
+ // less than full width in this calculation
+ if (mCurrentScore < 20) indWidth = (mIndicatorWidth / 20) * mCurrentScore;
+ // Draw indicator
+ canvas.drawRect(
+ getPaddingLeft(),
+ getPaddingTop(),
+ indWidth,
+ mIndicatorHeight,
+ mIndicatorPaint
+ );
+ // Draw guides if true
+ if (mShowGuides) {
+ // TODO: Try and do this with a loop, for efficiency
+ // Draw bottom guide border
+ float positionY = getHeight() - getPaddingBottom() - getPaddingTop();
+ float notchHeight = (float) (positionY * 0.8);
+ canvas.drawLine(
+ getPaddingLeft(),
+ positionY,
+ getWidth() - getPaddingRight(),
+ positionY,
+ mGuidePaint);
+ // Show left-most notch
+ canvas.drawLine(
+ getPaddingLeft(),
+ positionY,
+ getPaddingLeft(),
+ notchHeight,
+ mGuidePaint
+ );
+ // Show middle-left notch
+ canvas.drawLine(
+ (float) (mIndicatorWidth * 0.25) + getPaddingLeft(),
+ positionY,
+ (float) (mIndicatorWidth * 0.25) + getPaddingLeft(),
+ notchHeight,
+ mGuidePaint
+ );
+ // Show the middle notch
+ canvas.drawLine(
+ (float) (mIndicatorWidth * 0.5) + getPaddingLeft(),
+ positionY,
+ (float) (mIndicatorWidth * 0.5) + getPaddingLeft(),
+ notchHeight,
+ mGuidePaint
+ );
+ // Show the middle-right notch
+ canvas.drawLine(
+ (float) (mIndicatorWidth * 0.75) + getPaddingLeft(),
+ positionY,
+ (float) (mIndicatorWidth * 0.75) + getPaddingLeft(),
+ notchHeight,
+ mGuidePaint
+ );
+ // Show the right-most notch
+ canvas.drawLine(
+ mIndicatorWidth + getPaddingLeft(),
+ positionY,
+ mIndicatorWidth + getPaddingLeft(),
+ notchHeight,
+ mGuidePaint
+ );
+ }
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java
new file mode 100644
index 000000000..d7270ff58
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java
@@ -0,0 +1,360 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Matt Allen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+import org.sufficientlysecure.keychain.R;
+
+/**
+ * Created by Matt Allen
+ * 01/07/14
+ * http://www.mattallensoftware.co.uk
+ * mattallen092@gmail.com
+ * <p/>
+ * https://github.com/matt-allen/android-password-strength-indicator
+ * <p/>
+ * <p>
+ * This View is designed to indicate how secure a user-entered password is in a visual way to
+ * relay to the user if they need to make it stronger. The strength of the password can be set
+ * at creation (or after) which will decide whether their password is strong enough.
+ * </p>
+ * <p/>
+ * <p>
+ * The password strength is decided by an index of 20. The minimum score needed to pass is 10
+ * which means the String has met the conditions imposed by the strength test, but can be improved.
+ * If the password scores 10-19 it is considered weak, and only if it scores 20 will it be
+ * considered strong.
+ * </p>
+ */
+public class PasswordStrengthView extends View {
+
+ protected static final int COLOR_FAIL = Color.parseColor("#e74c3c");
+ protected static final int COLOR_WEAK = Color.parseColor("#e67e22");
+ protected static final int COLOR_STRONG = Color.parseColor("#2ecc71");
+
+ protected int mMinWidth;
+ protected int mMinHeight;
+
+ protected Paint mIndicatorPaint;
+ protected Paint mGuidePaint;
+
+ protected int mIndicatorHeight;
+ protected int mIndicatorWidth;
+ protected int mCurrentScore;
+
+ protected int mColorFail;
+ protected int mColorWeak;
+ protected int mColorStrong;
+
+ protected boolean mShowGuides = true;
+
+ /**
+ * Used to define that the indicator should only be looking
+ * for a weak password. The bare minimum is used here to let
+ * the user continue.
+ */
+ public static final int STRENGTH_WEAK = 0;
+
+ /**
+ * A fairly strict rule for generating a password. It encourages a password that is
+ * less easy to crack.
+ */
+ public static final int STRENGTH_MEDIUM = 1;
+
+ /**
+ * A strong algorithm that encourages very strong passwords that should be fairly long, with
+ * non-alphanumeric, numbers, and upper case.
+ */
+ public static final int STRENGTH_STRONG = 2;
+
+ private int mStrengthRequirement = -1;
+ protected String mPassword;
+
+ public PasswordStrengthView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ TypedArray style = context.getTheme().obtainStyledAttributes(
+ attrs,
+ R.styleable.PasswordStrengthView,
+ 0, 0);
+
+ try {
+ mStrengthRequirement = style.getInteger(R.styleable.PasswordStrengthView_strength,
+ STRENGTH_MEDIUM);
+ mShowGuides = style.getBoolean(R.styleable.PasswordStrengthView_showGuides, true);
+ mColorFail = style.getColor(R.styleable.PasswordStrengthView_color_fail, COLOR_FAIL);
+ mColorWeak = style.getColor(R.styleable.PasswordStrengthView_color_weak, COLOR_WEAK);
+ mColorStrong = style.getColor(R.styleable.PasswordStrengthView_color_strong,
+ COLOR_STRONG);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ // Create and style the paint used for drawing the guide on the indicator
+ mGuidePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mGuidePaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ mGuidePaint.setColor(Color.BLACK);
+ // Create and style paint for indicator
+ mIndicatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mIndicatorPaint.setStyle(Paint.Style.FILL);
+ }
+
+ /**
+ * This view can determine if the password entered by the user is acceptable for
+ * use by your use case. This is based on the strength requirement you have set.
+ *
+ * @return True if requirement has been met
+ */
+ public boolean isStrengthRequirementMet() {
+ return (mCurrentScore >= 10);
+ }
+
+ /**
+ * Change the strength requirement of the password entered by the user. This will also
+ * re-check the password already entered against these new requirements.
+ *
+ * @param requiredStrength Use the public constants of this class to set
+ */
+ public void setStrengthRequirement(int requiredStrength) {
+ if (requiredStrength >= 0 && requiredStrength <= 2) {
+ mStrengthRequirement = requiredStrength;
+ if (mPassword != null && mPassword.length() > 0) {
+ generatePasswordScore();
+ // Update view with new score
+ invalidate();
+ requestLayout();
+ }
+ } else {
+ throw new IndexOutOfBoundsException("Input out of expected range");
+ }
+ }
+
+ /**
+ * Update the password string to check strength of
+ *
+ * @param passwordString String representation of user-input
+ */
+ public void setPassword(String passwordString) {
+ if (passwordString != null && passwordString.length() > 0) {
+ mPassword = passwordString;
+ generatePasswordScore();
+ } else {
+ mPassword = "";
+ mCurrentScore = 0;
+ }
+
+ // Update view with new score
+ invalidate();
+ requestLayout();
+ }
+
+ /**
+ * Private convenience method for adding to the password score
+ *
+ * @param score Amount to be added to current score
+ */
+ protected void addToPasswordScore(int score) {
+ int newScore = mCurrentScore + score;
+
+ // Limit max score
+ if (newScore > 20) {
+ mCurrentScore = 20;
+ } else {
+ mCurrentScore = newScore;
+ }
+ }
+
+ /**
+ * Call this to determine the current strength requirement set on the algorithm
+ *
+ * @return Int representation of the current strength set for the indicator
+ */
+ public int getStrengthRequirement() {
+ return mStrengthRequirement;
+ }
+
+ /**
+ * Generate a score based on the password. The password will already need to be stored
+ * as a class member before running this.
+ */
+ protected void generatePasswordScore() {
+ mCurrentScore = 0;
+ int upperCase = getUppercaseCount(mPassword);
+ int nonAlpha = getNonAlphanumericCount(mPassword);
+ int numbers = getNumberCount(mPassword);
+ switch (mStrengthRequirement) {
+ case STRENGTH_WEAK:
+ addToPasswordScore(mPassword.length() * 2);
+ addToPasswordScore(upperCase * 2);
+ addToPasswordScore(nonAlpha * 2);
+ addToPasswordScore(numbers * 2);
+ break;
+
+ case STRENGTH_MEDIUM:
+ addToPasswordScore(mPassword.length());
+ addToPasswordScore(upperCase);
+ addToPasswordScore(nonAlpha * 2);
+ addToPasswordScore(numbers);
+ break;
+
+ case STRENGTH_STRONG:
+ addToPasswordScore(mPassword.length() / 2);
+ // Cut the score in half to make this a very high requirement
+ addToPasswordScore(upperCase);
+ addToPasswordScore(nonAlpha);
+ addToPasswordScore(numbers);
+ break;
+ }
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldW, int oldH) {
+ super.onSizeChanged(w, h, oldW, oldH);
+ int paddingX = getPaddingLeft();
+ int paddingY = getPaddingTop();
+ mIndicatorHeight = h - paddingY;
+ mIndicatorWidth = w - paddingX;
+ }
+
+ /**
+ * The standard parts of the onMeasure needed to create the password strength
+ * indicator. Subclasses should call super.onMeasure, but also need to set
+ * the minimum height and width in the constructor.
+ *
+ * @param widthMeasureSpec The measurement given by the system
+ * @param heightMeasureSpec The measurement given by the system
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Set minimum space for the view to do it's thing
+ int minW = getPaddingLeft() + getPaddingRight() + mMinWidth;
+ int w = resolveSizeAndState(minW, widthMeasureSpec, 1);
+ // And give it enough height so it's visible
+ int minH = mMinHeight + getPaddingBottom() + getPaddingTop();
+ int h = resolveSizeAndState(minH, heightMeasureSpec, 0);
+ // Feed these back into UIKit
+ setMeasuredDimension(w, h);
+ }
+
+ /**
+ * Set the colour of the indicator {@code Paint} to one that is appropriate
+ * for the strength of the password.
+ */
+ protected void generateIndicatorColor() {
+ int color = mColorFail;
+ if (mCurrentScore >= 18) {
+ color = mColorStrong;
+ } else if (mCurrentScore >= 10) {
+ color = mColorWeak;
+ }
+ mIndicatorPaint.setColor(color);
+ }
+
+ /**
+ * Quick method to determine how many of the characters in a given string are upper case
+ *
+ * @param stringToCheck The string to examine
+ * @return Number of upper case characters
+ */
+ protected int getUppercaseCount(String stringToCheck) {
+ int score = 0;
+ int loops = stringToCheck.length() - 1;
+ for (int i = 0; i <= loops; i++) {
+ if (Character.isUpperCase(stringToCheck.charAt(i))) {
+ score++;
+ }
+ }
+ return score;
+ }
+
+ /**
+ * A convenience method to determine how many characters in the given String aren't
+ * letters or numbers.
+ *
+ * @param stringToCheck
+ * @return Number of characters that aren't numbers or letters
+ */
+ protected int getNonAlphanumericCount(String stringToCheck) {
+ int score = 0;
+ int loops = stringToCheck.length() - 1;
+ for (int i = 0; i <= loops; i++) {
+ if (!Character.isLetter(stringToCheck.charAt(i)) &&
+ !Character.isDigit(stringToCheck.charAt(i))) {
+ score++;
+ }
+ }
+ return score;
+ }
+
+ /**
+ * A convenience method for returning the count of numbers in a given String.
+ *
+ * @param stringToCheck
+ * @return The numbers of digits in the String
+ */
+ protected int getNumberCount(String stringToCheck) {
+ int score = 0;
+ int loops = stringToCheck.length() - 1;
+ for (int i = 0; i <= loops; i++) {
+ if (Character.isDigit(stringToCheck.charAt(i))) {
+ score++;
+ }
+ }
+ return score;
+ }
+
+ /**
+ * Set the guides to show on the view.<br />
+ * On the line style, the guides will show underneath<br />
+ * On the rounded style, the guides will be shown on the outer edges.<br />
+ * The view will be redrawn after the method is called.
+ *
+ * @param showGuides True if you want the guides to be shown
+ */
+ public void setShowGuides(boolean showGuides) {
+ mShowGuides = showGuides;
+ if (mPassword != null && mPassword.length() > 0) {
+ generatePasswordScore();
+ } else {
+ mCurrentScore = 0;
+ }
+
+ invalidate();
+ requestLayout();
+ }
+
+ /**
+ * Determine whether the view is showing the guides for the password score
+ *
+ * @return True if the guides are being shown
+ */
+ public boolean isShowingGuides() {
+ return mShowGuides;
+ }
+}