1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.util; 18 19 import com.android.internal.R; 20 21 /** 22 * State sets are arrays of positive ints where each element 23 * represents the state of a {@link android.view.View} (e.g. focused, 24 * selected, visible, etc.). A {@link android.view.View} may be in 25 * one or more of those states. 26 * 27 * A state spec is an array of signed ints where each element 28 * represents a required (if positive) or an undesired (if negative) 29 * {@link android.view.View} state. 30 * 31 * Utils dealing with state sets. 32 * 33 * In theory we could encapsulate the state set and state spec arrays 34 * and not have static methods here but there is some concern about 35 * performance since these methods are called during view drawing. 36 */ 37 38 public class StateSet { 39 /** @hide */ public StateSet() {} 40 41 public static final int[] WILD_CARD = new int[0]; 42 public static final int[] NOTHING = new int[] { 0 }; 43 44 /** 45 * Return whether the stateSetOrSpec is matched by all StateSets. 46 * 47 * @param stateSetOrSpec a state set or state spec. 48 */ 49 public static boolean isWildCard(int[] stateSetOrSpec) { 50 return stateSetOrSpec.length == 0 || stateSetOrSpec[0] == 0; 51 } 52 53 /** 54 * Return whether the stateSet matches the desired stateSpec. 55 * 56 * @param stateSpec an array of required (if positive) or 57 * prohibited (if negative) {@link android.view.View} states. 58 * @param stateSet an array of {@link android.view.View} states 59 */ 60 public static boolean stateSetMatches(int[] stateSpec, int[] stateSet) { 61 if (stateSet == null) { 62 return (stateSpec == null || isWildCard(stateSpec)); 63 } 64 int stateSpecSize = stateSpec.length; 65 int stateSetSize = stateSet.length; 66 for (int i = 0; i < stateSpecSize; i++) { 67 int stateSpecState = stateSpec[i]; 68 if (stateSpecState == 0) { 69 // We've reached the end of the cases to match against. 70 return true; 71 } 72 final boolean mustMatch; 73 if (stateSpecState > 0) { 74 mustMatch = true; 75 } else { 76 // We use negative values to indicate must-NOT-match states. 77 mustMatch = false; 78 stateSpecState = -stateSpecState; 79 } 80 boolean found = false; 81 for (int j = 0; j < stateSetSize; j++) { 82 final int state = stateSet[j]; 83 if (state == 0) { 84 // We've reached the end of states to match. 85 if (mustMatch) { 86 // We didn't find this must-match state. 87 return false; 88 } else { 89 // Continue checking other must-not-match states. 90 break; 91 } 92 } 93 if (state == stateSpecState) { 94 if (mustMatch) { 95 found = true; 96 // Continue checking other other must-match states. 97 break; 98 } else { 99 // Any match of a must-not-match state returns false. 100 return false; 101 } 102 } 103 } 104 if (mustMatch && !found) { 105 // We've reached the end of states to match and we didn't 106 // find a must-match state. 107 return false; 108 } 109 } 110 return true; 111 } 112 113 /** 114 * Return whether the state matches the desired stateSpec. 115 * 116 * @param stateSpec an array of required (if positive) or 117 * prohibited (if negative) {@link android.view.View} states. 118 * @param state a {@link android.view.View} state 119 */ 120 public static boolean stateSetMatches(int[] stateSpec, int state) { 121 int stateSpecSize = stateSpec.length; 122 for (int i = 0; i < stateSpecSize; i++) { 123 int stateSpecState = stateSpec[i]; 124 if (stateSpecState == 0) { 125 // We've reached the end of the cases to match against. 126 return true; 127 } 128 if (stateSpecState > 0) { 129 if (state != stateSpecState) { 130 return false; 131 } 132 } else { 133 // We use negative values to indicate must-NOT-match states. 134 if (state == -stateSpecState) { 135 // We matched a must-not-match case. 136 return false; 137 } 138 } 139 } 140 return true; 141 } 142 143 public static int[] trimStateSet(int[] states, int newSize) { 144 if (states.length == newSize) { 145 return states; 146 } 147 148 int[] trimmedStates = new int[newSize]; 149 System.arraycopy(states, 0, trimmedStates, 0, newSize); 150 return trimmedStates; 151 } 152 153 public static String dump(int[] states) { 154 StringBuilder sb = new StringBuilder(); 155 156 int count = states.length; 157 for (int i = 0; i < count; i++) { 158 159 switch (states[i]) { 160 case R.attr.state_window_focused: 161 sb.append("W "); 162 break; 163 case R.attr.state_pressed: 164 sb.append("P "); 165 break; 166 case R.attr.state_selected: 167 sb.append("S "); 168 break; 169 case R.attr.state_focused: 170 sb.append("F "); 171 break; 172 case R.attr.state_enabled: 173 sb.append("E "); 174 break; 175 } 176 } 177 178 return sb.toString(); 179 } 180 } 181