OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / core / java / android / view / Gravity.java
1 /*
2  * Copyright (C) 2006 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.view;
18 import android.graphics.Rect;
19
20 /**
21  * Standard constants and tools for placing an object within a potentially
22  * larger container.
23  */
24 public class Gravity
25 {
26     /** Constant indicating that no gravity has been set **/
27     public static final int NO_GRAVITY = 0x0000;
28     
29     /** Raw bit indicating the gravity for an axis has been specified. */
30     public static final int AXIS_SPECIFIED = 0x0001;
31
32     /** Raw bit controlling how the left/top edge is placed. */
33     public static final int AXIS_PULL_BEFORE = 0x0002;
34     /** Raw bit controlling how the right/bottom edge is placed. */
35     public static final int AXIS_PULL_AFTER = 0x0004;
36     /** Raw bit controlling whether the right/bottom edge is clipped to its
37      * container, based on the gravity direction being applied. */
38     public static final int AXIS_CLIP = 0x0008;
39
40     /** Bits defining the horizontal axis. */
41     public static final int AXIS_X_SHIFT = 0;
42     /** Bits defining the vertical axis. */
43     public static final int AXIS_Y_SHIFT = 4;
44
45     /** Push object to the top of its container, not changing its size. */
46     public static final int TOP = (AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_Y_SHIFT;
47     /** Push object to the bottom of its container, not changing its size. */
48     public static final int BOTTOM = (AXIS_PULL_AFTER|AXIS_SPECIFIED)<<AXIS_Y_SHIFT;
49     /** Push object to the left of its container, not changing its size. */
50     public static final int LEFT = (AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_X_SHIFT;
51     /** Push object to the right of its container, not changing its size. */
52     public static final int RIGHT = (AXIS_PULL_AFTER|AXIS_SPECIFIED)<<AXIS_X_SHIFT;
53
54     /** Place object in the vertical center of its container, not changing its
55      *  size. */
56     public static final int CENTER_VERTICAL = AXIS_SPECIFIED<<AXIS_Y_SHIFT;
57     /** Grow the vertical size of the object if needed so it completely fills
58      *  its container. */
59     public static final int FILL_VERTICAL = TOP|BOTTOM;
60
61     /** Place object in the horizontal center of its container, not changing its
62      *  size. */
63     public static final int CENTER_HORIZONTAL = AXIS_SPECIFIED<<AXIS_X_SHIFT;
64     /** Grow the horizontal size of the object if needed so it completely fills
65      *  its container. */
66     public static final int FILL_HORIZONTAL = LEFT|RIGHT;
67
68     /** Place the object in the center of its container in both the vertical
69      *  and horizontal axis, not changing its size. */
70     public static final int CENTER = CENTER_VERTICAL|CENTER_HORIZONTAL;
71
72     /** Grow the horizontal and vertical size of the object if needed so it
73      *  completely fills its container. */
74     public static final int FILL = FILL_VERTICAL|FILL_HORIZONTAL;
75
76     /** Flag to clip the edges of the object to its container along the
77      *  vertical axis. */
78     public static final int CLIP_VERTICAL = AXIS_CLIP<<AXIS_Y_SHIFT;
79     
80     /** Flag to clip the edges of the object to its container along the
81      *  horizontal axis. */
82     public static final int CLIP_HORIZONTAL = AXIS_CLIP<<AXIS_X_SHIFT;
83     
84     /**
85      * Binary mask to get the horizontal gravity of a gravity.
86      */
87     public static final int HORIZONTAL_GRAVITY_MASK = (AXIS_SPECIFIED |
88             AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_X_SHIFT;
89     /**
90      * Binary mask to get the vertical gravity of a gravity.
91      */
92     public static final int VERTICAL_GRAVITY_MASK = (AXIS_SPECIFIED |
93             AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_Y_SHIFT;
94
95     /** Special constant to enable clipping to an overall display along the
96      *  vertical dimension.  This is not applied by default by
97      *  {@link #apply(int, int, int, Rect, int, int, Rect)}; you must do so
98      *  yourself by calling {@link #applyDisplay}.
99      */
100     public static final int DISPLAY_CLIP_VERTICAL = 0x10000000;
101     
102     /** Special constant to enable clipping to an overall display along the
103      *  horizontal dimension.  This is not applied by default by
104      *  {@link #apply(int, int, int, Rect, int, int, Rect)}; you must do so
105      *  yourself by calling {@link #applyDisplay}.
106      */
107     public static final int DISPLAY_CLIP_HORIZONTAL = 0x01000000;
108     
109     /**
110      * Apply a gravity constant to an object.
111      * 
112      * @param gravity The desired placement of the object, as defined by the
113      *                constants in this class.
114      * @param w The horizontal size of the object.
115      * @param h The vertical size of the object.
116      * @param container The frame of the containing space, in which the object
117      *                  will be placed.  Should be large enough to contain the
118      *                  width and height of the object.
119      * @param outRect Receives the computed frame of the object in its
120      *                container.
121      */
122     public static void apply(int gravity, int w, int h, Rect container,
123                              Rect outRect) {
124         apply(gravity, w, h, container, 0, 0, outRect);
125     }
126
127     /**
128      * Apply a gravity constant to an object.
129      * 
130      * @param gravity The desired placement of the object, as defined by the
131      *                constants in this class.
132      * @param w The horizontal size of the object.
133      * @param h The vertical size of the object.
134      * @param container The frame of the containing space, in which the object
135      *                  will be placed.  Should be large enough to contain the
136      *                  width and height of the object.
137      * @param xAdj Offset to apply to the X axis.  If gravity is LEFT this
138      *             pushes it to the right; if gravity is RIGHT it pushes it to
139      *             the left; if gravity is CENTER_HORIZONTAL it pushes it to the
140      *             right or left; otherwise it is ignored.
141      * @param yAdj Offset to apply to the Y axis.  If gravity is TOP this pushes
142      *             it down; if gravity is BOTTOM it pushes it up; if gravity is
143      *             CENTER_VERTICAL it pushes it down or up; otherwise it is
144      *             ignored.
145      * @param outRect Receives the computed frame of the object in its
146      *                container.
147      */
148     public static void apply(int gravity, int w, int h, Rect container,
149                              int xAdj, int yAdj, Rect outRect) {
150         switch (gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_X_SHIFT)) {
151             case 0:
152                 outRect.left = container.left
153                         + ((container.right - container.left - w)/2) + xAdj;
154                 outRect.right = outRect.left + w;
155                 if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT))
156                         == (AXIS_CLIP<<AXIS_X_SHIFT)) {
157                     if (outRect.left < container.left) {
158                         outRect.left = container.left;
159                     }
160                     if (outRect.right > container.right) {
161                         outRect.right = container.right;
162                     }
163                 }
164                 break;
165             case AXIS_PULL_BEFORE<<AXIS_X_SHIFT:
166                 outRect.left = container.left + xAdj;
167                 outRect.right = outRect.left + w;
168                 if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT))
169                         == (AXIS_CLIP<<AXIS_X_SHIFT)) {
170                     if (outRect.right > container.right) {
171                         outRect.right = container.right;
172                     }
173                 }
174                 break;
175             case AXIS_PULL_AFTER<<AXIS_X_SHIFT:
176                 outRect.right = container.right - xAdj;
177                 outRect.left = outRect.right - w;
178                 if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT))
179                         == (AXIS_CLIP<<AXIS_X_SHIFT)) {
180                     if (outRect.left < container.left) {
181                         outRect.left = container.left;
182                     }
183                 }
184                 break;
185             default:
186                 outRect.left = container.left + xAdj;
187                 outRect.right = container.right + xAdj;
188                 break;
189         }
190         
191         switch (gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_Y_SHIFT)) {
192             case 0:
193                 outRect.top = container.top
194                         + ((container.bottom - container.top - h)/2) + yAdj;
195                 outRect.bottom = outRect.top + h;
196                 if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT))
197                         == (AXIS_CLIP<<AXIS_Y_SHIFT)) {
198                     if (outRect.top < container.top) {
199                         outRect.top = container.top;
200                     }
201                     if (outRect.bottom > container.bottom) {
202                         outRect.bottom = container.bottom;
203                     }
204                 }
205                 break;
206             case AXIS_PULL_BEFORE<<AXIS_Y_SHIFT:
207                 outRect.top = container.top + yAdj;
208                 outRect.bottom = outRect.top + h;
209                 if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT))
210                         == (AXIS_CLIP<<AXIS_Y_SHIFT)) {
211                     if (outRect.bottom > container.bottom) {
212                         outRect.bottom = container.bottom;
213                     }
214                 }
215                 break;
216             case AXIS_PULL_AFTER<<AXIS_Y_SHIFT:
217                 outRect.bottom = container.bottom - yAdj;
218                 outRect.top = outRect.bottom - h;
219                 if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT))
220                         == (AXIS_CLIP<<AXIS_Y_SHIFT)) {
221                     if (outRect.top < container.top) {
222                         outRect.top = container.top;
223                     }
224                 }
225                 break;
226             default:
227                 outRect.top = container.top + yAdj;
228                 outRect.bottom = container.bottom + yAdj;
229                 break;
230         }
231     }
232
233     /**
234      * Apply additional gravity behavior based on the overall "display" that an
235      * object exists in.  This can be used after
236      * {@link #apply(int, int, int, Rect, int, int, Rect)} to place the object
237      * within a visible display.  By default this moves or clips the object
238      * to be visible in the display; the gravity flags
239      * {@link #DISPLAY_CLIP_HORIZONTAL} and {@link #DISPLAY_CLIP_VERTICAL}
240      * can be used to change this behavior.
241      * 
242      * @param gravity Gravity constants to modify the placement within the
243      * display.
244      * @param display The rectangle of the display in which the object is
245      * being placed.
246      * @param inoutObj Supplies the current object position; returns with it
247      * modified if needed to fit in the display.
248      */
249     public static void applyDisplay(int gravity, Rect display, Rect inoutObj) {
250         if ((gravity&DISPLAY_CLIP_VERTICAL) != 0) {
251             if (inoutObj.top < display.top) inoutObj.top = display.top;
252             if (inoutObj.bottom > display.bottom) inoutObj.bottom = display.bottom;
253         } else {
254             int off = 0;
255             if (inoutObj.top < display.top) off = display.top-inoutObj.top;
256             else if (inoutObj.bottom > display.bottom) off = display.bottom-inoutObj.bottom;
257             if (off != 0) {
258                 if (inoutObj.height() > (display.bottom-display.top)) {
259                     inoutObj.top = display.top;
260                     inoutObj.bottom = display.bottom;
261                 } else {
262                     inoutObj.top += off;
263                     inoutObj.bottom += off;
264                 }
265             }
266         }
267         
268         if ((gravity&DISPLAY_CLIP_HORIZONTAL) != 0) {
269             if (inoutObj.left < display.left) inoutObj.left = display.left;
270             if (inoutObj.right > display.right) inoutObj.right = display.right;
271         } else {
272             int off = 0;
273             if (inoutObj.left < display.left) off = display.left-inoutObj.left;
274             else if (inoutObj.right > display.right) off = display.right-inoutObj.right;
275             if (off != 0) {
276                 if (inoutObj.width() > (display.right-display.left)) {
277                     inoutObj.left = display.left;
278                     inoutObj.right = display.right;
279                 } else {
280                     inoutObj.left += off;
281                     inoutObj.right += off;
282                 }
283             }
284         }
285     }
286     
287     /**
288      * <p>Indicate whether the supplied gravity has a vertical pull.</p>
289      *
290      * @param gravity the gravity to check for vertical pull
291      * @return true if the supplied gravity has a vertical pull
292      */
293     public static boolean isVertical(int gravity) {
294         return gravity > 0 && (gravity & VERTICAL_GRAVITY_MASK) != 0;
295     }
296
297     /**
298      * <p>Indicate whether the supplied gravity has an horizontal pull.</p>
299      *
300      * @param gravity the gravity to check for horizontal pull
301      * @return true if the supplied gravity has an horizontal pull
302      */
303     public static boolean isHorizontal(int gravity) {
304         return gravity > 0 && (gravity & HORIZONTAL_GRAVITY_MASK) != 0;
305     }
306 }