kind, T[] array, T element) {
+ if (array != null) {
+ final int length = array.length;
+ for (int i = 0; i < length; i++) {
+ if (array[i] == element) {
+ if (length == 1) {
+ return null;
+ }
+ T[] result = (T[])Array.newInstance(kind, length - 1);
+ System.arraycopy(array, 0, result, 0, i);
+ System.arraycopy(array, i + 1, result, i, length - i - 1);
+ return result;
+ }
+ }
+ }
+ return array;
+ }
+
+ public static int[] appendInt(int[] cur, int val) {
+ if (cur == null) {
+ return new int[] { val };
+ }
+ final int N = cur.length;
+ for (int i = 0; i < N; i++) {
+ if (cur[i] == val) {
+ return cur;
+ }
+ }
+ int[] ret = new int[N + 1];
+ System.arraycopy(cur, 0, ret, 0, N);
+ ret[N] = val;
+ return ret;
+ }
+
+ public static int[] removeInt(int[] cur, int val) {
+ if (cur == null) {
+ return null;
+ }
+ final int N = cur.length;
+ for (int i = 0; i < N; i++) {
+ if (cur[i] == val) {
+ int[] ret = new int[N - 1];
+ if (i > 0) {
+ System.arraycopy(cur, 0, ret, 0, i);
+ }
+ if (i < (N - 1)) {
+ System.arraycopy(cur, i + 1, ret, i, N - i - 1);
+ }
+ return ret;
+ }
+ }
+ return cur;
+ }
+}
diff --git a/library/src/com/atermenji/android/iconicdroid/util/ColorStateList.java b/library/src/com/atermenji/android/iconicdroid/util/ColorStateList.java
new file mode 100644
index 0000000..a3c9632
--- /dev/null
+++ b/library/src/com/atermenji/android/iconicdroid/util/ColorStateList.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2007 The Android Open Source 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.atermenji.android.iconicdroid.util;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.util.StateSet;
+import android.util.Xml;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+
+/**
+ *
+ * Lets you map {@link android.view.View} state sets to colors.
+ *
+ * {@link android.content.res.ColorStateList}s are created from XML resource files defined in the
+ * "color" subdirectory directory of an application's resource directory. The XML file contains
+ * a single "selector" element with a number of "item" elements inside. For example:
+ *
+ *
+ * <selector xmlns:android="http://schemas.android.com/apk/res/android">
+ * <item android:state_focused="true" android:color="@color/testcolor1"/>
+ * <item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" />
+ * <item android:state_enabled="false" android:color="@color/testcolor3" />
+ * <item android:color="@color/testcolor5"/>
+ * </selector>
+ *
+ *
+ * This defines a set of state spec / color pairs where each state spec specifies a set of
+ * states that a view must either be in or not be in and the color specifies the color associated
+ * with that spec. The list of state specs will be processed in order of the items in the XML file.
+ * An item with no state spec is considered to match any set of states and is generally useful as
+ * a final item to be used as a default. Note that if you have such an item before any other items
+ * in the list then any subsequent items will end up being ignored.
+ * For more information, see the guide to Color State
+ * List Resource.
+ */
+public class ColorStateList implements Parcelable {
+
+ private int[][] mStateSpecs; // must be parallel to mColors
+ private int[] mColors; // must be parallel to mStateSpecs
+ private int mDefaultColor = 0xffff0000;
+
+ private static final int[][] EMPTY = new int[][] { new int[0] };
+ private static final SparseArray> sCache =
+ new SparseArray>();
+
+ private ColorStateList() { }
+
+ /**
+ * Creates a ColorStateList that returns the specified mapping from
+ * states to colors.
+ */
+ public ColorStateList(int[][] states, int[] colors) {
+ mStateSpecs = states;
+ mColors = colors;
+
+ if (states.length > 0) {
+ mDefaultColor = colors[0];
+
+ for (int i = 0; i < states.length; i++) {
+ if (states[i].length == 0) {
+ mDefaultColor = colors[i];
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates or retrieves a ColorStateList that always returns a single color.
+ */
+ public static ColorStateList valueOf(int color) {
+ // TODO: should we collect these eventually?
+ synchronized (sCache) {
+ WeakReference ref = sCache.get(color);
+ ColorStateList csl = ref != null ? ref.get() : null;
+
+ if (csl != null) {
+ return csl;
+ }
+
+ csl = new ColorStateList(EMPTY, new int[] { color });
+ sCache.put(color, new WeakReference(csl));
+ return csl;
+ }
+ }
+
+ /**
+ * Create a ColorStateList from an XML document, given a set of {@link Resources}.
+ */
+ public static ColorStateList createFromXml(Resources r, XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+
+ int type;
+ while ((type=parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ return createFromXmlInner(r, parser, attrs);
+ }
+
+ /* Create from inside an XML document. Called on a parser positioned at
+ * a tag in an XML document, tries to create a ColorStateList from that tag.
+ * Returns null if the tag is not a valid ColorStateList.
+ */
+ private static ColorStateList createFromXmlInner(Resources r, XmlPullParser parser,
+ AttributeSet attrs) throws XmlPullParserException, IOException {
+
+ ColorStateList colorStateList;
+
+ final String name = parser.getName();
+
+ if (name.equals("selector")) {
+ colorStateList = new ColorStateList();
+ } else {
+ throw new XmlPullParserException(
+ parser.getPositionDescription() + ": invalid drawable tag " + name);
+ }
+
+ colorStateList.inflate(r, parser, attrs);
+ return colorStateList;
+ }
+
+ /**
+ * Creates a new ColorStateList that has the same states and
+ * colors as this one but where each color has the specified alpha value
+ * (0-255).
+ */
+ public ColorStateList withAlpha(int alpha) {
+ int[] colors = new int[mColors.length];
+
+ int len = colors.length;
+ for (int i = 0; i < len; i++) {
+ colors[i] = (mColors[i] & 0xFFFFFF) | (alpha << 24);
+ }
+
+ return new ColorStateList(mStateSpecs, colors);
+ }
+
+ /**
+ * Fill in this object based on the contents of an XML "selector" element.
+ */
+ private void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
+ throws XmlPullParserException, IOException {
+
+ int type;
+
+ final int innerDepth = parser.getDepth()+1;
+ int depth;
+
+ int listAllocated = 20;
+ int listSize = 0;
+ int[] colorList = new int[listAllocated];
+ int[][] stateSpecList = new int[listAllocated][];
+
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && ((depth=parser.getDepth()) >= innerDepth
+ || type != XmlPullParser.END_TAG)) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (depth > innerDepth || !parser.getName().equals("item")) {
+ continue;
+ }
+
+ int colorRes = 0;
+ int color = 0xffff0000;
+ boolean haveColor = false;
+
+ int i;
+ int j = 0;
+ final int numAttrs = attrs.getAttributeCount();
+ int[] stateSpec = new int[numAttrs];
+ for (i = 0; i < numAttrs; i++) {
+ final int stateResId = attrs.getAttributeNameResource(i);
+ if (stateResId == 0) break;
+ if (stateResId == android.R.attr.color) {
+ colorRes = attrs.getAttributeResourceValue(i, 0);
+
+ if (colorRes == 0) {
+ color = attrs.getAttributeIntValue(i, color);
+ haveColor = true;
+ }
+ } else {
+ stateSpec[j++] = attrs.getAttributeBooleanValue(i, false)
+ ? stateResId
+ : -stateResId;
+ }
+ }
+ stateSpec = StateSet.trimStateSet(stateSpec, j);
+
+ if (colorRes != 0) {
+ color = r.getColor(colorRes);
+ } else if (!haveColor) {
+ throw new XmlPullParserException(
+ parser.getPositionDescription()
+ + ": - tag requires a 'android:color' attribute.");
+ }
+
+ if (listSize == 0 || stateSpec.length == 0) {
+ mDefaultColor = color;
+ }
+
+ if (listSize + 1 >= listAllocated) {
+ listAllocated = ArrayUtils.idealIntArraySize(listSize + 1);
+
+ int[] ncolor = new int[listAllocated];
+ System.arraycopy(colorList, 0, ncolor, 0, listSize);
+
+ int[][] nstate = new int[listAllocated][];
+ System.arraycopy(stateSpecList, 0, nstate, 0, listSize);
+
+ colorList = ncolor;
+ stateSpecList = nstate;
+ }
+
+ colorList[listSize] = color;
+ stateSpecList[listSize] = stateSpec;
+ listSize++;
+ }
+
+ mColors = new int[listSize];
+ mStateSpecs = new int[listSize][];
+ System.arraycopy(colorList, 0, mColors, 0, listSize);
+ System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize);
+ }
+
+ public boolean isStateful() {
+ return mStateSpecs.length > 1;
+ }
+
+ public int[][] getStates() {
+ return mStateSpecs;
+ }
+
+ public int[] getColors() {
+ return mColors;
+ }
+
+ /**
+ * Return the color associated with the given set of {@link android.view.View} states.
+ *
+ * @param stateSet an array of {@link android.view.View} states
+ * @param defaultColor the color to return if there's not state spec in this
+ * {@link ColorStateList} that matches the stateSet.
+ *
+ * @return the color associated with that set of states in this {@link ColorStateList}.
+ */
+ public int getColorForState(int[] stateSet, int defaultColor) {
+ final int setLength = mStateSpecs.length;
+ for (int i = 0; i < setLength; i++) {
+ int[] stateSpec = mStateSpecs[i];
+ if (StateSet.stateSetMatches(stateSpec, stateSet)) {
+ return mColors[i];
+ }
+ }
+ return defaultColor;
+ }
+
+ /**
+ * Return the default color in this {@link ColorStateList}.
+ *
+ * @return the default color in this {@link ColorStateList}.
+ */
+ public int getDefaultColor() {
+ return mDefaultColor;
+ }
+
+ public String toString() {
+ return "ColorStateList{" +
+ "mStateSpecs=" + Arrays.deepToString(mStateSpecs) +
+ "mColors=" + Arrays.toString(mColors) +
+ "mDefaultColor=" + mDefaultColor + '}';
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ final int N = mStateSpecs.length;
+ dest.writeInt(N);
+ for (int i=0; i CREATOR =
+ new Parcelable.Creator() {
+ public ColorStateList[] newArray(int size) {
+ return new ColorStateList[size];
+ }
+
+ public ColorStateList createFromParcel(Parcel source) {
+ final int N = source.readInt();
+ int[][] stateSpecs = new int[N][];
+ for (int i=0; i