package eu.hgross.blaubot.android.views; import android.graphics.drawable.Drawable; import eu.hgross.blaubot.android.R; import eu.hgross.blaubot.core.State; import eu.hgross.blaubot.core.statemachine.states.IBlaubotState; import android.content.Context; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.widget.EditText; import java.util.regex.Pattern; /** * Helper for some commonly used methods around the debug views. */ public class ViewUtils { /** * Retrieve the corresponding drawable by the blaubot state * * @param ctx the context * @param state the blaubot state to retrieve the drawable for * @return the drawable * @throws java.lang.IllegalStateException if the state is not mapped to an icon */ public static Drawable getDrawableForBlaubotState(Context ctx, IBlaubotState state) { final State stateEnum = State.getStateByStatemachineClass(state.getClass()); return getDrawableForBlaubotState(ctx, stateEnum); } /** * Retrieve the corresponding drawable by the blaubot state * * @param ctx the context * @param stateEnum the blaubot state to retrieve the drawable for * @return the drawable * @throws java.lang.IllegalStateException if the state is not mapped to an icon */ public static Drawable getDrawableForBlaubotState(Context ctx, State stateEnum) { final int resId; if (stateEnum.equals(State.Stopped)) { resId = R.drawable.ic_stopped; } else if (stateEnum.equals(State.Free)) { resId = R.drawable.ic_free; } else if (stateEnum.equals(State.Peasant)) { resId = R.drawable.ic_peasant; } else if (stateEnum.equals(State.Prince)) { resId = R.drawable.ic_prince; } else if (stateEnum.equals(State.King)) { resId = R.drawable.ic_king; } else { throw new IllegalStateException("State " + stateEnum + " unknown."); } return ctx.getResources().getDrawable(resId); } /** * {@link TextWatcher} adapter class bound to a {@link View} */ public abstract class SettingsTextWatcher implements TextWatcher { protected View view; public SettingsTextWatcher(View view) { this.view = view; } @Override public void afterTextChanged(Editable s) { if (validate(s.toString())) { ((EditText) view).setError(null); onSettingChanged(s.toString()); } else { ((EditText) view).setError("Invalid value"); } } /** * Called iff the text was changed and validation was successful. * * @param text the new text */ public abstract void onSettingChanged(String text); /** * @param val the current edittext's state * @return true if val is a valid input, false otherwise */ protected abstract boolean validate(String val); @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } } /** * A Regex based SettingsTextWatcher to simplify validation */ public abstract class RegexSettingsTextWatcher extends SettingsTextWatcher { private final Pattern pattern; public RegexSettingsTextWatcher(View view, String pattern) { super(view); this.pattern = Pattern.compile(pattern); } protected boolean validate(String val) { return pattern.matcher(val).matches(); }; } private static final Pattern URL_PATTERN = Pattern.compile("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"); /** * Validates url path segements. * * @param val the url path segment to be validated * @return true iff val is a valid URL path (without protocol, host, port) */ public static boolean validateURLPathSegment(String val) { val = "http://example.com" + val; return URL_PATTERN.matcher(val).matches(); } private static final Pattern validIpAddressRegex = Pattern.compile("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"); private static final Pattern validHostnameRegex = Pattern.compile("^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$"); /** * Validates a hostname * * @param hostname the hostname to be validated * @return true, iff hostname is a valid hostname (not an ip) */ public static boolean isValidHostname(String hostname) { return validHostnameRegex.matcher(hostname).matches(); } /** * Checks wheter an ipv4 address is valid * * @param ip the ip to be checked * @return true, iff ip is a valid ip address */ public static boolean isValidIpAddress(String ip) { return validHostnameRegex.matcher(ip).matches(); } /** * Converts a byte size into a human readable sting * @param bytes the number of bytes * @param si if true, the output will be in si units * @return the human readable string */ public static String humanReadableByteCount(final long bytes, final boolean si) { final int unit = si ? 1000 : 1024; if (bytes < unit) return bytes + " B"; final int exp = (int) (Math.log(bytes) / Math.log(unit)); final String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i"); return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); } }