1/*
2 * Copyright (C) 2013 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
18package android.support.v4.view;
19
20import static android.os.Build.VERSION.SDK_INT;
21
22import android.graphics.Rect;
23import android.view.Gravity;
24
25/**
26 * Compatibility shim for accessing newer functionality from {@link android.view.Gravity}.
27 */
28public final class GravityCompat {
29    /** Raw bit controlling whether the layout direction is relative or not (START/END instead of
30     * absolute LEFT/RIGHT).
31     */
32    public static final int RELATIVE_LAYOUT_DIRECTION = 0x00800000;
33
34    /** Push object to x-axis position at the start of its container, not changing its size. */
35    public static final int START = RELATIVE_LAYOUT_DIRECTION | Gravity.LEFT;
36
37    /** Push object to x-axis position at the end of its container, not changing its size. */
38    public static final int END = RELATIVE_LAYOUT_DIRECTION | Gravity.RIGHT;
39
40    /**
41     * Binary mask for the horizontal gravity and script specific direction bit.
42     */
43    public static final int RELATIVE_HORIZONTAL_GRAVITY_MASK = START | END;
44
45    /**
46     * Apply a gravity constant to an object and take care if layout direction is RTL or not.
47     *
48     * @param gravity The desired placement of the object, as defined by the
49     *                constants in this class.
50     * @param w The horizontal size of the object.
51     * @param h The vertical size of the object.
52     * @param container The frame of the containing space, in which the object
53     *                  will be placed.  Should be large enough to contain the
54     *                  width and height of the object.
55     * @param outRect Receives the computed frame of the object in its
56     *                container.
57     * @param layoutDirection The layout direction.
58     *
59     * @see ViewCompat#LAYOUT_DIRECTION_LTR
60     * @see ViewCompat#LAYOUT_DIRECTION_RTL
61     */
62    public static void apply(int gravity, int w, int h, Rect container,
63            Rect outRect, int layoutDirection) {
64        if (SDK_INT >= 17) {
65            Gravity.apply(gravity, w, h, container, outRect, layoutDirection);
66        } else {
67            Gravity.apply(gravity, w, h, container, outRect);
68        }
69    }
70
71    /**
72     * Apply a gravity constant to an object.
73     *
74     * @param gravity The desired placement of the object, as defined by the
75     *                constants in this class.
76     * @param w The horizontal size of the object.
77     * @param h The vertical size of the object.
78     * @param container The frame of the containing space, in which the object
79     *                  will be placed.  Should be large enough to contain the
80     *                  width and height of the object.
81     * @param xAdj Offset to apply to the X axis.  If gravity is LEFT this
82     *             pushes it to the right; if gravity is RIGHT it pushes it to
83     *             the left; if gravity is CENTER_HORIZONTAL it pushes it to the
84     *             right or left; otherwise it is ignored.
85     * @param yAdj Offset to apply to the Y axis.  If gravity is TOP this pushes
86     *             it down; if gravity is BOTTOM it pushes it up; if gravity is
87     *             CENTER_VERTICAL it pushes it down or up; otherwise it is
88     *             ignored.
89     * @param outRect Receives the computed frame of the object in its
90     *                container.
91     * @param layoutDirection The layout direction.
92     *
93     * @see ViewCompat#LAYOUT_DIRECTION_LTR
94     * @see ViewCompat#LAYOUT_DIRECTION_RTL
95     */
96    public static void apply(int gravity, int w, int h, Rect container,
97            int xAdj, int yAdj, Rect outRect, int layoutDirection) {
98        if (SDK_INT >= 17) {
99            Gravity.apply(gravity, w, h, container, xAdj, yAdj, outRect, layoutDirection);
100        } else {
101            Gravity.apply(gravity, w, h, container, xAdj, yAdj, outRect);
102        }
103    }
104
105    /**
106     * Apply additional gravity behavior based on the overall "display" that an
107     * object exists in.  This can be used after
108     * {@link android.view.Gravity#apply(int, int, int, Rect, int, int, Rect)} to place the object
109     * within a visible display.  By default this moves or clips the object
110     * to be visible in the display; the gravity flags
111     * {@link android.view.Gravity#DISPLAY_CLIP_HORIZONTAL} and
112     * {@link android.view.Gravity#DISPLAY_CLIP_VERTICAL} can be used to change this behavior.
113     *
114     * @param gravity Gravity constants to modify the placement within the
115     * display.
116     * @param display The rectangle of the display in which the object is
117     * being placed.
118     * @param inoutObj Supplies the current object position; returns with it
119     * modified if needed to fit in the display.
120     * @param layoutDirection The layout direction.
121     *
122     * @see ViewCompat#LAYOUT_DIRECTION_LTR
123     * @see ViewCompat#LAYOUT_DIRECTION_RTL
124     */
125    public static void applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection) {
126        if (SDK_INT >= 17) {
127            Gravity.applyDisplay(gravity, display, inoutObj, layoutDirection);
128        } else {
129            Gravity.applyDisplay(gravity, display, inoutObj);
130        }
131    }
132
133    /**
134     * <p>Convert script specific gravity to absolute horizontal value.</p>
135     *
136     * if horizontal direction is LTR, then START will set LEFT and END will set RIGHT.
137     * if horizontal direction is RTL, then START will set RIGHT and END will set LEFT.
138     *
139     *
140     * @param gravity The gravity to convert to absolute (horizontal) values.
141     * @param layoutDirection The layout direction.
142     * @return gravity converted to absolute (horizontal) values.
143     */
144    public static int getAbsoluteGravity(int gravity, int layoutDirection) {
145        if (SDK_INT >= 17) {
146            return Gravity.getAbsoluteGravity(gravity, layoutDirection);
147        } else {
148            // Just strip off the relative bit to get LEFT/RIGHT.
149            return gravity & ~RELATIVE_LAYOUT_DIRECTION;
150        }
151    }
152
153    private GravityCompat() {}
154}
155