Home | History | Annotate | Download | only in util
      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      */
     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      */
     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      */
    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 
    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 
    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