19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.util; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.R; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * State sets are arrays of positive ints where each element 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * represents the state of a {@link android.view.View} (e.g. focused, 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selected, visible, etc.). A {@link android.view.View} may be in 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * one or more of those states. 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A state spec is an array of signed ints where each element 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * represents a required (if positive) or an undesired (if negative) 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.View} state. 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Utils dealing with state sets. 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In theory we could encapsulate the state set and state spec arrays 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and not have static methods here but there is some concern about 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * performance since these methods are called during view drawing. 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class StateSet { 39c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** 40c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette * The order here is very important to 41c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette * {@link android.view.View#getDrawableState()} 42c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette */ 43c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette private static final int[][] VIEW_STATE_SETS; 44c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette 45c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 46c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static final int VIEW_STATE_WINDOW_FOCUSED = 1; 47c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 48c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static final int VIEW_STATE_SELECTED = 1 << 1; 49c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 50c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static final int VIEW_STATE_FOCUSED = 1 << 2; 51c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 52c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static final int VIEW_STATE_ENABLED = 1 << 3; 53c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 54c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static final int VIEW_STATE_PRESSED = 1 << 4; 55c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 56c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static final int VIEW_STATE_ACTIVATED = 1 << 5; 57c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 58c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static final int VIEW_STATE_ACCELERATED = 1 << 6; 59c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 60c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static final int VIEW_STATE_HOVERED = 1 << 7; 61c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 62c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8; 63c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 64c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static final int VIEW_STATE_DRAG_HOVERED = 1 << 9; 65c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette 66c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette static final int[] VIEW_STATE_IDS = new int[] { 67c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette R.attr.state_window_focused, VIEW_STATE_WINDOW_FOCUSED, 68c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette R.attr.state_selected, VIEW_STATE_SELECTED, 69c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette R.attr.state_focused, VIEW_STATE_FOCUSED, 70c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette R.attr.state_enabled, VIEW_STATE_ENABLED, 71c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette R.attr.state_pressed, VIEW_STATE_PRESSED, 72c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette R.attr.state_activated, VIEW_STATE_ACTIVATED, 73c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette R.attr.state_accelerated, VIEW_STATE_ACCELERATED, 74c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette R.attr.state_hovered, VIEW_STATE_HOVERED, 75c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette R.attr.state_drag_can_accept, VIEW_STATE_DRAG_CAN_ACCEPT, 76c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette R.attr.state_drag_hovered, VIEW_STATE_DRAG_HOVERED 77c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette }; 78c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette 79c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette static { 80c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette if ((VIEW_STATE_IDS.length / 2) != R.styleable.ViewDrawableStates.length) { 81c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette throw new IllegalStateException( 82c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette "VIEW_STATE_IDs array length does not match ViewDrawableStates style array"); 83c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette } 84c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette 85c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette final int[] orderedIds = new int[VIEW_STATE_IDS.length]; 86c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) { 87c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette final int viewState = R.styleable.ViewDrawableStates[i]; 88c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette for (int j = 0; j < VIEW_STATE_IDS.length; j += 2) { 89c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette if (VIEW_STATE_IDS[j] == viewState) { 90c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette orderedIds[i * 2] = viewState; 91c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1]; 92c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette } 93c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette } 94c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette } 95c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette 96c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette final int NUM_BITS = VIEW_STATE_IDS.length / 2; 97c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette VIEW_STATE_SETS = new int[1 << NUM_BITS][]; 98c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette for (int i = 0; i < VIEW_STATE_SETS.length; i++) { 99c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette final int numBits = Integer.bitCount(i); 100c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette final int[] set = new int[numBits]; 101c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette int pos = 0; 102c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette for (int j = 0; j < orderedIds.length; j += 2) { 103c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette if ((i & orderedIds[j + 1]) != 0) { 104c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette set[pos++] = orderedIds[j]; 105c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette } 106c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette } 107c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette VIEW_STATE_SETS[i] = set; 108c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette } 109c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette } 110c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette 111c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 112c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public static int[] get(int mask) { 113c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette if (mask >= VIEW_STATE_SETS.length) { 114c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette throw new IllegalArgumentException("Invalid state set mask"); 115c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette } 116c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette return VIEW_STATE_SETS[mask]; 117c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette } 118c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette 119c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette /** @hide */ 120c5b95c20b6fd3f4e63147efb22dd19c657b17001Alan Viverette public StateSet() {} 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12257bf3d9c2d0d73324480a8ca383828cdc4bcb143Jeff Brown /** 12357bf3d9c2d0d73324480a8ca383828cdc4bcb143Jeff Brown * A state specification that will be matched by all StateSets. 12457bf3d9c2d0d73324480a8ca383828cdc4bcb143Jeff Brown */ 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int[] WILD_CARD = new int[0]; 12657bf3d9c2d0d73324480a8ca383828cdc4bcb143Jeff Brown 12757bf3d9c2d0d73324480a8ca383828cdc4bcb143Jeff Brown /** 12857bf3d9c2d0d73324480a8ca383828cdc4bcb143Jeff Brown * A state set that does not contain any valid states. 12957bf3d9c2d0d73324480a8ca383828cdc4bcb143Jeff Brown */ 130079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn public static final int[] NOTHING = new int[] { 0 }; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return whether the stateSetOrSpec is matched by all StateSets. 134a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson * 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param stateSetOrSpec a state set or state spec. 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean isWildCard(int[] stateSetOrSpec) { 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return stateSetOrSpec.length == 0 || stateSetOrSpec[0] == 0; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return whether the stateSet matches the desired stateSpec. 143a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson * 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param stateSpec an array of required (if positive) or 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * prohibited (if negative) {@link android.view.View} states. 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param stateSet an array of {@link android.view.View} states 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean stateSetMatches(int[] stateSpec, int[] stateSet) { 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stateSet == null) { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (stateSpec == null || isWildCard(stateSpec)); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int stateSpecSize = stateSpec.length; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int stateSetSize = stateSet.length; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < stateSpecSize; i++) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int stateSpecState = stateSpec[i]; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stateSpecState == 0) { 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We've reached the end of the cases to match against. 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean mustMatch; 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stateSpecState > 0) { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mustMatch = true; 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We use negative values to indicate must-NOT-match states. 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mustMatch = false; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stateSpecState = -stateSpecState; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean found = false; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < stateSetSize; j++) { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int state = stateSet[j]; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == 0) { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We've reached the end of states to match. 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mustMatch) { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We didn't find this must-match state. 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Continue checking other must-not-match states. 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == stateSpecState) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mustMatch) { 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project found = true; 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Continue checking other other must-match states. 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Any match of a must-not-match state returns false. 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mustMatch && !found) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We've reached the end of states to match and we didn't 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // find a must-match state. 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return whether the state matches the desired stateSpec. 203a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson * 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param stateSpec an array of required (if positive) or 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * prohibited (if negative) {@link android.view.View} states. 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param state a {@link android.view.View} state 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean stateSetMatches(int[] stateSpec, int state) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int stateSpecSize = stateSpec.length; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < stateSpecSize; i++) { 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int stateSpecState = stateSpec[i]; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stateSpecState == 0) { 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We've reached the end of the cases to match against. 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stateSpecState > 0) { 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state != stateSpecState) { 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We use negative values to indicate must-NOT-match states. 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == -stateSpecState) { 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We matched a must-not-match case. 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2314a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He /** 2324a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He * Check whether a list of state specs has an attribute specified. 2334a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He * @param stateSpecs a list of state specs we're checking. 2344a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He * @param attr an attribute we're looking for. 2354a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He * @return {@code true} if the attribute is contained in the state specs. 2364a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He * @hide 2374a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He */ 2384a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He public static boolean containsAttribute(int[][] stateSpecs, int attr) { 2394a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He if (stateSpecs != null) { 2404a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He for (int[] spec : stateSpecs) { 2414a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He if (spec == null) { 2424a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He break; 2434a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He } 2444a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He for (int specAttr : spec) { 2454a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He if (specAttr == attr || -specAttr == attr) { 2464a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He return true; 2474a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He } 2484a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He } 2494a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He } 2504a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He } 2514a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He return false; 2524a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He } 2534a81674b45b7250c4e2a80330371f7aa1c066d05Jiaquan He 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int[] trimStateSet(int[] states, int newSize) { 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (states.length == newSize) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return states; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] trimmedStates = new int[newSize]; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(states, 0, trimmedStates, 0, newSize); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return trimmedStates; 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 263a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String dump(int[] states) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 266a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = states.length; 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 269a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (states[i]) { 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case R.attr.state_window_focused: 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("W "); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case R.attr.state_pressed: 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("P "); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case R.attr.state_selected: 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("S "); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case R.attr.state_focused: 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("F "); 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case R.attr.state_enabled: 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("E "); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 286189d4f5b770eb45ea23e8c529cabc1ccdff6e83aAlan Viverette case R.attr.state_checked: 287189d4f5b770eb45ea23e8c529cabc1ccdff6e83aAlan Viverette sb.append("C "); 288189d4f5b770eb45ea23e8c529cabc1ccdff6e83aAlan Viverette break; 289189d4f5b770eb45ea23e8c529cabc1ccdff6e83aAlan Viverette case R.attr.state_activated: 290189d4f5b770eb45ea23e8c529cabc1ccdff6e83aAlan Viverette sb.append("A "); 291189d4f5b770eb45ea23e8c529cabc1ccdff6e83aAlan Viverette break; 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 294a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 298