2d7c1a19179afb2df04fc826b8bd349e1e6e2842
[platform/framework/web/crosswalk.git] / src / base / android / java / src / org / chromium / base / ApiCompatibilityUtils.java
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.base;
6
7 import android.animation.ValueAnimator;
8 import android.app.ActivityOptions;
9 import android.app.Notification;
10 import android.app.PendingIntent;
11 import android.content.Context;
12 import android.content.Intent;
13 import android.content.res.Configuration;
14 import android.graphics.drawable.Drawable;
15 import android.os.Build;
16 import android.os.Bundle;
17 import android.view.View;
18 import android.view.ViewGroup.MarginLayoutParams;
19 import android.view.ViewTreeObserver;
20 import android.widget.ImageView;
21 import android.widget.RemoteViews;
22 import android.widget.TextView;
23
24 /**
25  * Utility class to use new APIs that were added after ICS (API level 14).
26  */
27 public class ApiCompatibilityUtils {
28
29     private static final String TAG = "ApiCompatibilityUtils";
30
31     private ApiCompatibilityUtils() {
32     }
33
34     /**
35      * Returns true if view's layout direction is right-to-left.
36      *
37      * @param view the View whose layout is being considered
38      */
39     public static boolean isLayoutRtl(View view) {
40         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
41             return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
42         } else {
43             // All layouts are LTR before JB MR1.
44             return false;
45         }
46     }
47
48     /**
49      * @see Configuration#getLayoutDirection()
50      */
51     public static int getLayoutDirection(Configuration configuration) {
52         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
53             return configuration.getLayoutDirection();
54         } else {
55             // All layouts are LTR before JB MR1.
56             return View.LAYOUT_DIRECTION_LTR;
57         }
58     }
59
60     /**
61      * @return True if the running version of the Android supports printing.
62      */
63     public static boolean isPrintingSupported() {
64         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
65     }
66
67     /**
68      * @return True if the running version of the Android supports HTML clipboard.
69      */
70     public static boolean isHTMLClipboardSupported() {
71         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
72     }
73
74     /**
75      * @see android.view.View#setLayoutDirection(int)
76      */
77     public static void setLayoutDirection(View view, int layoutDirection) {
78         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
79             view.setLayoutDirection(layoutDirection);
80         } else {
81             // Do nothing. RTL layouts aren't supported before JB MR1.
82         }
83     }
84
85     /**
86      * @see android.view.View#setTextDirection(int)
87      */
88     public static void setTextAlignment(View view, int textAlignment) {
89         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
90             view.setTextAlignment(textAlignment);
91         } else {
92             // Do nothing. RTL text isn't supported before JB MR1.
93         }
94     }
95
96     /**
97      * @see android.view.ViewGroup.MarginLayoutParams#setMarginEnd(int)
98      */
99     public static void setMarginEnd(MarginLayoutParams layoutParams, int end) {
100         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
101             layoutParams.setMarginEnd(end);
102         } else {
103             layoutParams.rightMargin = end;
104         }
105     }
106
107     /**
108      * @see android.view.ViewGroup.MarginLayoutParams#getMarginEnd()
109      */
110     public static int getMarginEnd(MarginLayoutParams layoutParams) {
111         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
112             return layoutParams.getMarginEnd();
113         } else {
114             return layoutParams.rightMargin;
115         }
116     }
117
118     /**
119      * @see android.view.ViewGroup.MarginLayoutParams#setMarginStart(int)
120      */
121     public static void setMarginStart(MarginLayoutParams layoutParams, int start) {
122         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
123             layoutParams.setMarginStart(start);
124         } else {
125             layoutParams.leftMargin = start;
126         }
127     }
128
129     /**
130      * @see android.view.ViewGroup.MarginLayoutParams#getMarginStart()
131      */
132     public static int getMarginStart(MarginLayoutParams layoutParams) {
133         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
134             return layoutParams.getMarginStart();
135         } else {
136             return layoutParams.leftMargin;
137         }
138     }
139
140     /**
141      * @see android.view.View#setPaddingRelative(int, int, int, int)
142      */
143     public static void setPaddingRelative(View view, int start, int top, int end, int bottom) {
144         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
145             view.setPaddingRelative(start, top, end, bottom);
146         } else {
147             // Before JB MR1, all layouts are left-to-right, so start == left, etc.
148             view.setPadding(start, top, end, bottom);
149         }
150     }
151
152     /**
153      * @see android.view.View#getPaddingStart()
154      */
155     public static int getPaddingStart(View view) {
156         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
157             return view.getPaddingStart();
158         } else {
159             // Before JB MR1, all layouts are left-to-right, so start == left.
160             return view.getPaddingLeft();
161         }
162     }
163
164     /**
165      * @see android.view.View#getPaddingEnd()
166      */
167     public static int getPaddingEnd(View view) {
168         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
169             return view.getPaddingEnd();
170         } else {
171             // Before JB MR1, all layouts are left-to-right, so end == right.
172             return view.getPaddingRight();
173         }
174     }
175
176     /**
177      * @see android.widget.TextView#setCompoundDrawablesRelative(Drawable, Drawable, Drawable,
178      *      Drawable)
179      */
180     public static void setCompoundDrawablesRelative(TextView textView, Drawable start, Drawable top,
181             Drawable end, Drawable bottom) {
182         if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
183             // On JB MR1, due to a platform bug, setCompoundDrawablesRelative() is a no-op if the
184             // view has ever been measured. As a workaround, use setCompoundDrawables() directly.
185             // See: http://crbug.com/368196 and http://crbug.com/361709
186             boolean isRtl = isLayoutRtl(textView);
187             textView.setCompoundDrawables(isRtl ? end : start, top, isRtl ? start : end, bottom);
188         } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
189             textView.setCompoundDrawablesRelative(start, top, end, bottom);
190         } else {
191             textView.setCompoundDrawables(start, top, end, bottom);
192         }
193     }
194
195     /**
196      * @see android.widget.TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable,
197      *      Drawable, Drawable, Drawable)
198      */
199     public static void setCompoundDrawablesRelativeWithIntrinsicBounds(TextView textView,
200             Drawable start, Drawable top, Drawable end, Drawable bottom) {
201         if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
202             // Work around the platform bug described in setCompoundDrawablesRelative() above.
203             boolean isRtl = isLayoutRtl(textView);
204             textView.setCompoundDrawablesWithIntrinsicBounds(isRtl ? end : start, top,
205                     isRtl ? start : end, bottom);
206         } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
207             textView.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
208         } else {
209             textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
210         }
211     }
212
213     /**
214      * @see android.widget.TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int,
215      *      int)
216      */
217     public static void setCompoundDrawablesRelativeWithIntrinsicBounds(TextView textView,
218             int start, int top, int end, int bottom) {
219         if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
220             // Work around the platform bug described in setCompoundDrawablesRelative() above.
221             boolean isRtl = isLayoutRtl(textView);
222             textView.setCompoundDrawablesWithIntrinsicBounds(isRtl ? end : start, top,
223                     isRtl ? start : end, bottom);
224         } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
225             textView.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
226         } else {
227             textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
228         }
229     }
230
231     /**
232      * @see android.view.View#postInvalidateOnAnimation()
233      */
234     public static void postInvalidateOnAnimation(View view) {
235         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
236             view.postInvalidateOnAnimation();
237         } else {
238             view.postInvalidate();
239         }
240     }
241
242     /**
243      * @see android.view.View#postOnAnimation()
244      */
245     public static void postOnAnimation(View view, Runnable action) {
246         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
247             view.postOnAnimation(action);
248         } else {
249             view.postDelayed(action, getFrameTime());
250         }
251     }
252
253     /**
254      * @see android.view.View#postOnAnimationDelayed()
255      */
256     public static void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
257         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
258             view.postOnAnimationDelayed(action, delayMillis);
259         } else {
260             view.postDelayed(action, getFrameTime() + delayMillis);
261         }
262     }
263
264     private static long getFrameTime() {
265         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
266             return ValueAnimator.getFrameDelay();
267         } else {
268             // Any reasonable fake frame delay will have to do.
269             return 10;
270         }
271     }
272
273     /**
274      * @see android.widget.RemoteViews#setContentDescription(int, CharSequence)
275      */
276     public static void setContentDescriptionForRemoteView(RemoteViews remoteViews, int viewId,
277             CharSequence contentDescription) {
278         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
279             remoteViews.setContentDescription(viewId, contentDescription);
280         } else {
281             // setContentDescription() is unavailable in earlier versions.
282         }
283     }
284
285     /**
286      * @see android.app.Activity#startActivity(Intent, Bundle)
287      */
288     public static void startActivity(Context context, Intent intent, Bundle options) {
289         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
290             context.startActivity(intent, options);
291         } else {
292             context.startActivity(intent);
293         }
294     }
295
296     /**
297      * @see android.app.ActivityOptions#toBundle()
298      */
299     public static Bundle toBundle(ActivityOptions options) {
300         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
301             return options.toBundle();
302         } else {
303             return null;
304         }
305     }
306
307     // These methods have a new name, and the old name is deprecated.
308
309     /**
310      * @see android.view.View#setBackground(Drawable)
311      */
312     @SuppressWarnings("deprecation")
313     public static void setBackgroundForView(View view, Drawable drawable) {
314         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
315             view.setBackground(drawable);
316         } else {
317             view.setBackgroundDrawable(drawable);
318         }
319     }
320
321     /**
322      * @see android.view.ViewTreeObserver#removeOnGlobalLayoutListener()
323      */
324     @SuppressWarnings("deprecation")
325     public static void removeOnGlobalLayoutListener(
326             View view, ViewTreeObserver.OnGlobalLayoutListener listener) {
327         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
328             view.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
329         } else {
330             view.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
331         }
332     }
333
334     /**
335      * @see android.widget.ImageView#setImageAlpha(int)
336      */
337     @SuppressWarnings("deprecation")
338     public static void setImageAlpha(ImageView iv, int alpha) {
339         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
340             iv.setImageAlpha(alpha);
341         } else {
342             iv.setAlpha(alpha);
343         }
344     }
345
346     /**
347      * @see android.app.PendingIntent#getCreatorPackage()
348      */
349     @SuppressWarnings("deprecation")
350     public static String getCreatorPackage(PendingIntent intent) {
351         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
352             return intent.getCreatorPackage();
353         } else {
354             return intent.getTargetPackage();
355         }
356     }
357
358     /**
359      * @see android.app.Notification.Builder#setLocalOnly(boolean)
360      */
361     @SuppressWarnings("deprecation")
362     public static Notification build(Notification.Builder builder) {
363         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
364             return builder.build();
365         } else {
366             return builder.getNotification();
367         }
368     }
369 }