• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
40     public static final int[] WILD_CARD = new int[0];
41 
42     /**
43      * Return whether the stateSetOrSpec is matched by all StateSets.
44      *
45      * @param stateSetOrSpec a state set or state spec.
46      */
isWildCard(int[] stateSetOrSpec)47     public static boolean isWildCard(int[] stateSetOrSpec) {
48         return stateSetOrSpec.length == 0 || stateSetOrSpec[0] == 0;
49     }
50 
51     /**
52      * Return whether the stateSet matches the desired stateSpec.
53      *
54      * @param stateSpec an array of required (if positive) or
55      *        prohibited (if negative) {@link android.view.View} states.
56      * @param stateSet an array of {@link android.view.View} states
57      */
stateSetMatches(int[] stateSpec, int[] stateSet)58     public static boolean stateSetMatches(int[] stateSpec, int[] stateSet) {
59         if (stateSet == null) {
60             return (stateSpec == null || isWildCard(stateSpec));
61         }
62         int stateSpecSize = stateSpec.length;
63         int stateSetSize = stateSet.length;
64         for (int i = 0; i < stateSpecSize; i++) {
65             int stateSpecState = stateSpec[i];
66             if (stateSpecState == 0) {
67                 // We've reached the end of the cases to match against.
68                 return true;
69             }
70             final boolean mustMatch;
71             if (stateSpecState > 0) {
72                 mustMatch = true;
73             } else {
74                 // We use negative values to indicate must-NOT-match states.
75                 mustMatch = false;
76                 stateSpecState = -stateSpecState;
77             }
78             boolean found = false;
79             for (int j = 0; j < stateSetSize; j++) {
80                 final int state = stateSet[j];
81                 if (state == 0) {
82                     // We've reached the end of states to match.
83                     if (mustMatch) {
84                         // We didn't find this must-match state.
85                         return false;
86                     } else {
87                         // Continue checking other must-not-match states.
88                         break;
89                     }
90                 }
91                 if (state == stateSpecState) {
92                     if (mustMatch) {
93                         found = true;
94                         // Continue checking other other must-match states.
95                         break;
96                     } else {
97                         // Any match of a must-not-match state returns false.
98                         return false;
99                     }
100                 }
101             }
102             if (mustMatch && !found) {
103                 // We've reached the end of states to match and we didn't
104                 // find a must-match state.
105                 return false;
106             }
107         }
108         return true;
109     }
110 
111     /**
112      * Return whether the state matches the desired stateSpec.
113      *
114      * @param stateSpec an array of required (if positive) or
115      *        prohibited (if negative) {@link android.view.View} states.
116      * @param state a {@link android.view.View} state
117      */
stateSetMatches(int[] stateSpec, int state)118     public static boolean stateSetMatches(int[] stateSpec, int state) {
119         int stateSpecSize = stateSpec.length;
120         for (int i = 0; i < stateSpecSize; i++) {
121             int stateSpecState = stateSpec[i];
122             if (stateSpecState == 0) {
123                 // We've reached the end of the cases to match against.
124                 return true;
125             }
126             if (stateSpecState > 0) {
127                 if (state != stateSpecState) {
128                    return false;
129                 }
130             } else {
131                 // We use negative values to indicate must-NOT-match states.
132                 if (state == -stateSpecState) {
133                     // We matched a must-not-match case.
134                     return false;
135                 }
136             }
137         }
138         return true;
139     }
140 
trimStateSet(int[] states, int newSize)141     public static int[] trimStateSet(int[] states, int newSize) {
142         if (states.length == newSize) {
143             return states;
144         }
145 
146         int[] trimmedStates = new int[newSize];
147         System.arraycopy(states, 0, trimmedStates, 0, newSize);
148         return trimmedStates;
149     }
150 
dump(int[] states)151     public static String dump(int[] states) {
152         StringBuilder sb = new StringBuilder();
153 
154         int count = states.length;
155         for (int i = 0; i < count; i++) {
156 
157             switch (states[i]) {
158             case R.attr.state_window_focused:
159                 sb.append("W ");
160                 break;
161             case R.attr.state_pressed:
162                 sb.append("P ");
163                 break;
164             case R.attr.state_selected:
165                 sb.append("S ");
166                 break;
167             case R.attr.state_focused:
168                 sb.append("F ");
169                 break;
170             case R.attr.state_enabled:
171                 sb.append("E ");
172                 break;
173             }
174         }
175 
176         return sb.toString();
177     }
178 }
179