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     /** @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