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.widget;
18 
19 import java.util.ArrayList;
20 
21 /**
22  * ExpandableListPosition can refer to either a group's position or a child's
23  * position. Referring to a child's position requires both a group position (the
24  * group containing the child) and a child position (the child's position within
25  * that group). To create objects, use {@link #obtainChildPosition(int, int)} or
26  * {@link #obtainGroupPosition(int)}.
27  */
28 class ExpandableListPosition {
29 
30     private static final int MAX_POOL_SIZE = 5;
31     private static ArrayList<ExpandableListPosition> sPool =
32         new ArrayList<ExpandableListPosition>(MAX_POOL_SIZE);
33 
34     /**
35      * This data type represents a child position
36      */
37     public final static int CHILD = 1;
38 
39     /**
40      * This data type represents a group position
41      */
42     public final static int GROUP = 2;
43 
44     /**
45      * The position of either the group being referred to, or the parent
46      * group of the child being referred to
47      */
48     public int groupPos;
49 
50     /**
51      * The position of the child within its parent group
52      */
53     public int childPos;
54 
55     /**
56      * The position of the item in the flat list (optional, used internally when
57      * the corresponding flat list position for the group or child is known)
58      */
59     int flatListPos;
60 
61     /**
62      * What type of position this ExpandableListPosition represents
63      */
64     public int type;
65 
resetState()66     private void resetState() {
67         groupPos = 0;
68         childPos = 0;
69         flatListPos = 0;
70         type = 0;
71     }
72 
ExpandableListPosition()73     private ExpandableListPosition() {
74     }
75 
getPackedPosition()76     long getPackedPosition() {
77         if (type == CHILD) return ExpandableListView.getPackedPositionForChild(groupPos, childPos);
78         else return ExpandableListView.getPackedPositionForGroup(groupPos);
79     }
80 
obtainGroupPosition(int groupPosition)81     static ExpandableListPosition obtainGroupPosition(int groupPosition) {
82         return obtain(GROUP, groupPosition, 0, 0);
83     }
84 
obtainChildPosition(int groupPosition, int childPosition)85     static ExpandableListPosition obtainChildPosition(int groupPosition, int childPosition) {
86         return obtain(CHILD, groupPosition, childPosition, 0);
87     }
88 
obtainPosition(long packedPosition)89     static ExpandableListPosition obtainPosition(long packedPosition) {
90         if (packedPosition == ExpandableListView.PACKED_POSITION_VALUE_NULL) {
91             return null;
92         }
93 
94         ExpandableListPosition elp = getRecycledOrCreate();
95         elp.groupPos = ExpandableListView.getPackedPositionGroup(packedPosition);
96         if (ExpandableListView.getPackedPositionType(packedPosition) ==
97                 ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
98             elp.type = CHILD;
99             elp.childPos = ExpandableListView.getPackedPositionChild(packedPosition);
100         } else {
101             elp.type = GROUP;
102         }
103         return elp;
104     }
105 
obtain(int type, int groupPos, int childPos, int flatListPos)106     static ExpandableListPosition obtain(int type, int groupPos, int childPos, int flatListPos) {
107         ExpandableListPosition elp = getRecycledOrCreate();
108         elp.type = type;
109         elp.groupPos = groupPos;
110         elp.childPos = childPos;
111         elp.flatListPos = flatListPos;
112         return elp;
113     }
114 
getRecycledOrCreate()115     private static ExpandableListPosition getRecycledOrCreate() {
116         ExpandableListPosition elp;
117         synchronized (sPool) {
118             if (sPool.size() > 0) {
119                 elp = sPool.remove(0);
120             } else {
121                 return new ExpandableListPosition();
122             }
123         }
124         elp.resetState();
125         return elp;
126     }
127 
128     /**
129      * Do not call this unless you obtained this via ExpandableListPosition.obtain().
130      * PositionMetadata will handle recycling its own children.
131      */
recycle()132     public void recycle() {
133         synchronized (sPool) {
134             if (sPool.size() < MAX_POOL_SIZE) {
135                 sPool.add(this);
136             }
137         }
138     }
139 }
140