Home | History | Annotate | Download | only in internal
      1 /*
      2  * Copyright (C) 2010 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 com.android.inputmethod.keyboard.internal;
     18 
     19 import android.util.Log;
     20 
     21 import com.android.inputmethod.latin.utils.CollectionUtils;
     22 
     23 import java.util.ArrayList;
     24 
     25 public final class PointerTrackerQueue {
     26     private static final String TAG = PointerTrackerQueue.class.getSimpleName();
     27     private static final boolean DEBUG = false;
     28 
     29     public interface Element {
     30         public boolean isModifier();
     31         public boolean isInSlidingKeyInput();
     32         public void onPhantomUpEvent(long eventTime);
     33         public void cancelTrackingForAction();
     34     }
     35 
     36     private static final int INITIAL_CAPACITY = 10;
     37     // Note: {@link #mExpandableArrayOfActivePointers} and {@link #mArraySize} are synchronized by
     38     // {@link #mExpandableArrayOfActivePointers}
     39     private final ArrayList<Element> mExpandableArrayOfActivePointers =
     40             CollectionUtils.newArrayList(INITIAL_CAPACITY);
     41     private int mArraySize = 0;
     42 
     43     public int size() {
     44         synchronized (mExpandableArrayOfActivePointers) {
     45             return mArraySize;
     46         }
     47     }
     48 
     49     public void add(final Element pointer) {
     50         synchronized (mExpandableArrayOfActivePointers) {
     51             if (DEBUG) {
     52                 Log.d(TAG, "add: " + pointer + " " + this);
     53             }
     54             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
     55             final int arraySize = mArraySize;
     56             if (arraySize < expandableArray.size()) {
     57                 expandableArray.set(arraySize, pointer);
     58             } else {
     59                 expandableArray.add(pointer);
     60             }
     61             mArraySize = arraySize + 1;
     62         }
     63     }
     64 
     65     public void remove(final Element pointer) {
     66         synchronized (mExpandableArrayOfActivePointers) {
     67             if (DEBUG) {
     68                 Log.d(TAG, "remove: " + pointer + " " + this);
     69             }
     70             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
     71             final int arraySize = mArraySize;
     72             int newIndex = 0;
     73             for (int index = 0; index < arraySize; index++) {
     74                 final Element element = expandableArray.get(index);
     75                 if (element == pointer) {
     76                     if (newIndex != index) {
     77                         Log.w(TAG, "Found duplicated element in remove: " + pointer);
     78                     }
     79                     continue; // Remove this element from the expandableArray.
     80                 }
     81                 if (newIndex != index) {
     82                     // Shift this element toward the beginning of the expandableArray.
     83                     expandableArray.set(newIndex, element);
     84                 }
     85                 newIndex++;
     86             }
     87             mArraySize = newIndex;
     88         }
     89     }
     90 
     91     public Element getOldestElement() {
     92         synchronized (mExpandableArrayOfActivePointers) {
     93             return (mArraySize == 0) ? null : mExpandableArrayOfActivePointers.get(0);
     94         }
     95     }
     96 
     97     public void releaseAllPointersOlderThan(final Element pointer, final long eventTime) {
     98         synchronized (mExpandableArrayOfActivePointers) {
     99             if (DEBUG) {
    100                 Log.d(TAG, "releaseAllPoniterOlderThan: " + pointer + " " + this);
    101             }
    102             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    103             final int arraySize = mArraySize;
    104             int newIndex, index;
    105             for (newIndex = index = 0; index < arraySize; index++) {
    106                 final Element element = expandableArray.get(index);
    107                 if (element == pointer) {
    108                     break; // Stop releasing elements.
    109                 }
    110                 if (!element.isModifier()) {
    111                     element.onPhantomUpEvent(eventTime);
    112                     continue; // Remove this element from the expandableArray.
    113                 }
    114                 if (newIndex != index) {
    115                     // Shift this element toward the beginning of the expandableArray.
    116                     expandableArray.set(newIndex, element);
    117                 }
    118                 newIndex++;
    119             }
    120             // Shift rest of the expandableArray.
    121             int count = 0;
    122             for (; index < arraySize; index++) {
    123                 final Element element = expandableArray.get(index);
    124                 if (element == pointer) {
    125                     count++;
    126                     if (count > 1) {
    127                         Log.w(TAG, "Found duplicated element in releaseAllPointersOlderThan: "
    128                                 + pointer);
    129                     }
    130                 }
    131                 if (newIndex != index) {
    132                     // Shift this element toward the beginning of the expandableArray.
    133                     expandableArray.set(newIndex, expandableArray.get(index));
    134                 }
    135                 newIndex++;
    136             }
    137             mArraySize = newIndex;
    138         }
    139     }
    140 
    141     public void releaseAllPointers(final long eventTime) {
    142         releaseAllPointersExcept(null, eventTime);
    143     }
    144 
    145     public void releaseAllPointersExcept(final Element pointer, final long eventTime) {
    146         synchronized (mExpandableArrayOfActivePointers) {
    147             if (DEBUG) {
    148                 if (pointer == null) {
    149                     Log.d(TAG, "releaseAllPoniters: " + this);
    150                 } else {
    151                     Log.d(TAG, "releaseAllPoniterExcept: " + pointer + " " + this);
    152                 }
    153             }
    154             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    155             final int arraySize = mArraySize;
    156             int newIndex = 0, count = 0;
    157             for (int index = 0; index < arraySize; index++) {
    158                 final Element element = expandableArray.get(index);
    159                 if (element == pointer) {
    160                     count++;
    161                     if (count > 1) {
    162                         Log.w(TAG, "Found duplicated element in releaseAllPointersExcept: "
    163                                 + pointer);
    164                     }
    165                 } else {
    166                     element.onPhantomUpEvent(eventTime);
    167                     continue; // Remove this element from the expandableArray.
    168                 }
    169                 if (newIndex != index) {
    170                     // Shift this element toward the beginning of the expandableArray.
    171                     expandableArray.set(newIndex, element);
    172                 }
    173                 newIndex++;
    174             }
    175             mArraySize = newIndex;
    176         }
    177     }
    178 
    179     public boolean hasModifierKeyOlderThan(final Element pointer) {
    180         synchronized (mExpandableArrayOfActivePointers) {
    181             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    182             final int arraySize = mArraySize;
    183             for (int index = 0; index < arraySize; index++) {
    184                 final Element element = expandableArray.get(index);
    185                 if (element == pointer) {
    186                     return false; // Stop searching modifier key.
    187                 }
    188                 if (element.isModifier()) {
    189                     return true;
    190                 }
    191             }
    192             return false;
    193         }
    194     }
    195 
    196     public boolean isAnyInSlidingKeyInput() {
    197         synchronized (mExpandableArrayOfActivePointers) {
    198             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    199             final int arraySize = mArraySize;
    200             for (int index = 0; index < arraySize; index++) {
    201                 final Element element = expandableArray.get(index);
    202                 if (element.isInSlidingKeyInput()) {
    203                     return true;
    204                 }
    205             }
    206             return false;
    207         }
    208     }
    209 
    210     public void cancelAllPointerTrackers() {
    211         synchronized (mExpandableArrayOfActivePointers) {
    212             if (DEBUG) {
    213                 Log.d(TAG, "cancelAllPointerTracker: " + this);
    214             }
    215             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    216             final int arraySize = mArraySize;
    217             for (int index = 0; index < arraySize; index++) {
    218                 final Element element = expandableArray.get(index);
    219                 element.cancelTrackingForAction();
    220             }
    221         }
    222     }
    223 
    224     @Override
    225     public String toString() {
    226         synchronized (mExpandableArrayOfActivePointers) {
    227             final StringBuilder sb = new StringBuilder();
    228             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    229             final int arraySize = mArraySize;
    230             for (int index = 0; index < arraySize; index++) {
    231                 final Element element = expandableArray.get(index);
    232                 if (sb.length() > 0) {
    233                     sb.append(" ");
    234                 }
    235                 sb.append(element.toString());
    236             }
    237             return "[" + sb.toString() + "]";
    238         }
    239     }
    240 }
    241