Utils.java revision 3dc5e908a825b879978ba523d9099dc2255da9a5
1146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/*
2146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
3146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
4146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * you may not use this file except in compliance with the License.
6146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * You may obtain a copy of the License at
7146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
8146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
10146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * See the License for the specific language governing permissions and
14146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * limitations under the License.
15146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */
16146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
17146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpackage com.android.calendar;
18146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
19146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport static android.provider.Calendar.EVENT_BEGIN_TIME;
20e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
21146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context;
22146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Intent;
23e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chanimport android.content.SharedPreferences;
24ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.database.Cursor;
25a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErikimport android.database.MatrixCursor;
26ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.graphics.drawable.Drawable;
27ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.graphics.drawable.GradientDrawable;
281ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.net.Uri;
29eb10fa8bee049e0052b5cb53dcfbdaccef9f2740Erikimport android.text.TextUtils;
30146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time;
311ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.util.Log;
32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.animation.AlphaAnimation;
33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.ViewFlipper;
34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
3556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashiimport java.util.Calendar;
36235d59cf61769ec8ab777d81cd1ceb2e7530f439Erikimport java.util.HashSet;
371ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport java.util.List;
38ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport java.util.Map;
3956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
40146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class Utils {
413dc5e908a825b879978ba523d9099dc2255da9a5Erik    private static final boolean DEBUG = true;
423dc5e908a825b879978ba523d9099dc2255da9a5Erik    private static final String TAG = "CalUtils";
43ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int CLEAR_ALPHA_MASK = 0x00FFFFFF;
44ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int HIGH_ALPHA = 255 << 24;
45ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int MED_ALPHA = 180 << 24;
46ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int LOW_ALPHA = 150 << 24;
47ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
48ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    protected static final String OPEN_EMAIL_MARKER = " <";
49ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    protected static final String CLOSE_EMAIL_MARKER = ">";
50ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    /* The corner should be rounded on the top right and bottom right */
51ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final float[] CORNERS = new float[] {0, 0, 5, 5, 5, 5, 0, 0};
52ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
53235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    private volatile static boolean mFirstTZRequest = true;
54235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    private volatile static boolean mTZQueryInProgress = false;
55235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik
56235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    private volatile static boolean mUseHomeTZ = false;
57235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    private volatile static String mHomeTZ = Time.getCurrentTimezone();
58235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik
59235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    private static HashSet<Runnable> mTZCallbacks = new HashSet<Runnable>();
60ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
61146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static void startActivity(Context context, String className, long time) {
62146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Intent intent = new Intent(Intent.ACTION_VIEW);
63146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
64146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        intent.setClassName(context, className);
65146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        intent.putExtra(EVENT_BEGIN_TIME, time);
6623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
67146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
68146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        context.startActivity(intent);
69146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
70146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
7145efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan    static String getSharedPreference(Context context, String key, String defaultValue) {
72a17725e24d51b7a6f002dd5afd3270c8eeea0dbeJeff Hamilton        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
7345efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan        return prefs.getString(key, defaultValue);
7445efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan    }
7545efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan
76235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    /**
773dc5e908a825b879978ba523d9099dc2255da9a5Erik     * Writes a new home time zone to the db.
783dc5e908a825b879978ba523d9099dc2255da9a5Erik     *
793dc5e908a825b879978ba523d9099dc2255da9a5Erik     * Updates the home time zone in the db asynchronously and updates
803dc5e908a825b879978ba523d9099dc2255da9a5Erik     * the local cache. Sending a time zone of **tbd** will cause it to
813dc5e908a825b879978ba523d9099dc2255da9a5Erik     * be set to the device's time zone. null or empty tz will be ignored.
823dc5e908a825b879978ba523d9099dc2255da9a5Erik     *
833dc5e908a825b879978ba523d9099dc2255da9a5Erik     * @param context The calling activity
843dc5e908a825b879978ba523d9099dc2255da9a5Erik     * @param timeZone The time zone to set Calendar to, or **tbd**
853dc5e908a825b879978ba523d9099dc2255da9a5Erik     */
863dc5e908a825b879978ba523d9099dc2255da9a5Erik    public static void setTimeZone(Context context, String timeZone) {
873dc5e908a825b879978ba523d9099dc2255da9a5Erik        if (TextUtils.isEmpty(timeZone)) {
883dc5e908a825b879978ba523d9099dc2255da9a5Erik            if (DEBUG) {
893dc5e908a825b879978ba523d9099dc2255da9a5Erik                Log.d(TAG, "Empty time zone, nothing to be done.");
903dc5e908a825b879978ba523d9099dc2255da9a5Erik            }
913dc5e908a825b879978ba523d9099dc2255da9a5Erik            return;
923dc5e908a825b879978ba523d9099dc2255da9a5Erik        }
933dc5e908a825b879978ba523d9099dc2255da9a5Erik        synchronized (mTZCallbacks) {
943dc5e908a825b879978ba523d9099dc2255da9a5Erik            if (CalendarPreferenceActivity.LOCAL_TZ.equals(timeZone)) {
953dc5e908a825b879978ba523d9099dc2255da9a5Erik                if (!mUseHomeTZ) {
963dc5e908a825b879978ba523d9099dc2255da9a5Erik                    return;
973dc5e908a825b879978ba523d9099dc2255da9a5Erik                }
983dc5e908a825b879978ba523d9099dc2255da9a5Erik                mUseHomeTZ = false;
993dc5e908a825b879978ba523d9099dc2255da9a5Erik            } else {
1003dc5e908a825b879978ba523d9099dc2255da9a5Erik                if (TextUtils.equals(mHomeTZ, timeZone)) {
1013dc5e908a825b879978ba523d9099dc2255da9a5Erik                    return;
1023dc5e908a825b879978ba523d9099dc2255da9a5Erik                }
1033dc5e908a825b879978ba523d9099dc2255da9a5Erik                mUseHomeTZ = true;
1043dc5e908a825b879978ba523d9099dc2255da9a5Erik                mHomeTZ = timeZone;
1053dc5e908a825b879978ba523d9099dc2255da9a5Erik            }
1063dc5e908a825b879978ba523d9099dc2255da9a5Erik        }
1073dc5e908a825b879978ba523d9099dc2255da9a5Erik        setSharedPreference(context, CalendarPreferenceActivity.KEY_HOME_TZ_ENABLED, mUseHomeTZ);
1083dc5e908a825b879978ba523d9099dc2255da9a5Erik        if (mUseHomeTZ) {
1093dc5e908a825b879978ba523d9099dc2255da9a5Erik            setSharedPreference(context, CalendarPreferenceActivity.KEY_HOME_TZ, mHomeTZ);
1103dc5e908a825b879978ba523d9099dc2255da9a5Erik        }
1113dc5e908a825b879978ba523d9099dc2255da9a5Erik        // TODO async update db
1123dc5e908a825b879978ba523d9099dc2255da9a5Erik    }
1133dc5e908a825b879978ba523d9099dc2255da9a5Erik
1143dc5e908a825b879978ba523d9099dc2255da9a5Erik    /**
115235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * Gets the time zone that Calendar should be displayed in
116235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     *
117235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * This is a helper method to get the appropriate time zone for Calendar. If this
118235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * is the first time this method has been called it will initiate an asynchronous
119235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * query to verify that the data in preferences is correct. The callback supplied
120235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * will only be called if this query returns a value other than what is stored in
121235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * preferences and should cause the calling activity to refresh anything that
122235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * depends on calling this method.
123235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     *
124235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * @param context The calling activity
125235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * @param callback The runnable that should execute if a query returns new values
126235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * @return The string value representing the time zone Calendar should display
127235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     */
128235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    public static String getTimeZone(Context context, Runnable callback) {
129235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik        synchronized (mTZCallbacks){
130235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik            if (mFirstTZRequest) {
131235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mTZQueryInProgress = true;
132235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mFirstTZRequest = false;
133235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik
134235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
135235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mUseHomeTZ = prefs.getBoolean(
136235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                        CalendarPreferenceActivity.KEY_HOME_TZ_ENABLED, false);
137235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mHomeTZ = prefs.getString(
138235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                        CalendarPreferenceActivity.KEY_HOME_TZ, Time.getCurrentTimezone());
139235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // TODO kick off async query
140235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // When the async query returns it should synchronize on
141235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // mTZCallbacks, update mUseHomeTZ, mHomeTZ, and the
142235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // preferences, set mTZQueryInProgress to false, and call all
143235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // the runnables in mTZCallbacks.
144235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // TODO remove this line when we have a query
145235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mTZQueryInProgress = false;
146235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik            }
147235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik            if (mTZQueryInProgress) {
148235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mTZCallbacks.add(callback);
149235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik            }
150235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik        }
151235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik        return mUseHomeTZ ? mHomeTZ : Time.getCurrentTimezone();
152235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    }
153235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik
15445efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan    static void setSharedPreference(Context context, String key, String value) {
155a17725e24d51b7a6f002dd5afd3270c8eeea0dbeJeff Hamilton        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
15645efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan        SharedPreferences.Editor editor = prefs.edit();
15745efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan        editor.putString(key, value);
15845efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan        editor.commit();
15945efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan    }
16045efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan
1613dc5e908a825b879978ba523d9099dc2255da9a5Erik    static void setSharedPreference(Context context, String key, boolean value) {
1623dc5e908a825b879978ba523d9099dc2255da9a5Erik        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
1633dc5e908a825b879978ba523d9099dc2255da9a5Erik        SharedPreferences.Editor editor = prefs.edit();
1643dc5e908a825b879978ba523d9099dc2255da9a5Erik        editor.putBoolean(key, value);
1653dc5e908a825b879978ba523d9099dc2255da9a5Erik        editor.commit();
1663dc5e908a825b879978ba523d9099dc2255da9a5Erik    }
1673dc5e908a825b879978ba523d9099dc2255da9a5Erik
168e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan    static void setDefaultView(Context context, int viewId) {
169e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        String activityString = CalendarApplication.ACTIVITY_NAMES[viewId];
170e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
171a17725e24d51b7a6f002dd5afd3270c8eeea0dbeJeff Hamilton        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
172e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        SharedPreferences.Editor editor = prefs.edit();
173e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        if (viewId == CalendarApplication.AGENDA_VIEW_ID ||
174e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan                viewId == CalendarApplication.DAY_VIEW_ID) {
175e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan            // Record the (new) detail start view only for Agenda and Day
176e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan            editor.putString(CalendarPreferenceActivity.KEY_DETAILED_VIEW, activityString);
177e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        }
178e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
179e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        // Record the (new) start view
180e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        editor.putString(CalendarPreferenceActivity.KEY_START_VIEW, activityString);
181e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        editor.commit();
182e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan    }
183e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final Time timeFromIntent(Intent intent) {
185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Time time = new Time();
186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        time.set(timeFromIntentInMillis(intent));
187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return time;
188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
190a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    public static MatrixCursor matrixCursorFromCursor(Cursor cursor) {
191a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames());
192a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        int numColumns = cursor.getColumnCount();
193a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        String data[] = new String[numColumns];
194a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        cursor.moveToPosition(-1);
195a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        while (cursor.moveToNext()) {
196a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            for (int i = 0; i < numColumns; i++) {
197a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                data[i] = cursor.getString(i);
198a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            }
199a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            newCursor.addRow(data);
200a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
201a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        return newCursor;
202a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    }
203a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
204a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    /**
205a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     * Compares two cursors to see if they contain the same data.
206a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     *
207a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     * @return Returns true of the cursors contain the same data and are not null, false
208a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     * otherwise
209a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     */
210a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    public static boolean compareCursors(Cursor c1, Cursor c2) {
211a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if(c1 == null || c2 == null) {
212a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
213a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
214a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
215a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        int numColumns = c1.getColumnCount();
216a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if (numColumns != c2.getColumnCount()) {
217a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
218a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
219a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
220a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if (c1.getCount() != c2.getCount()) {
221a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
222a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
223a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
224a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        c1.moveToPosition(-1);
225a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        c2.moveToPosition(-1);
226a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        while(c1.moveToNext() && c2.moveToNext()) {
227a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            for(int i = 0; i < numColumns; i++) {
228eb10fa8bee049e0052b5cb53dcfbdaccef9f2740Erik                if(!TextUtils.equals(c1.getString(i), c2.getString(i))) {
229a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                    return false;
230a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                }
231a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            }
232a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
233a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
234a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        return true;
235a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    }
236a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * If the given intent specifies a time (in milliseconds since the epoch),
239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * then that time is returned. Otherwise, the current time is returned.
240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final long timeFromIntentInMillis(Intent intent) {
242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // If the time was specified, then use that.  Otherwise, use the current time.
2431ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        Uri data = intent.getData();
244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long millis = intent.getLongExtra(EVENT_BEGIN_TIME, -1);
2451ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        if (millis == -1 && data != null && data.isHierarchical()) {
2461ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik            List<String> path = data.getPathSegments();
247eca5d33e4230cf6ac3acfe3fabf853f9275f98caErik            if(path.size() == 2 && path.get(0).equals("time")) {
2481ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                try {
2491ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                    millis = Long.valueOf(data.getLastPathSegment());
2501ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                } catch (NumberFormatException e) {
2511ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                    Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time " +
2521ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                            "found. Using current time.");
2531ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                }
2541ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik            }
2551ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        }
25676727b7a9cf780f200414548b9d454bf9a701e3eErik        if (millis <= 0) {
257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            millis = System.currentTimeMillis();
258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return millis;
260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final void applyAlphaAnimation(ViewFlipper v) {
263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        AlphaAnimation in = new AlphaAnimation(0.0f, 1.0f);
264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        in.setStartOffset(0);
266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        in.setDuration(500);
267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        AlphaAnimation out = new AlphaAnimation(1.0f, 0.0f);
269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        out.setStartOffset(0);
271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        out.setDuration(500);
272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        v.setInAnimation(in);
274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        v.setOutAnimation(out);
275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
277ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    public static Drawable getColorChip(int color) {
278ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        /*
279ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * We want the color chip to have a nice gradient using
280ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * the color of the calendar. To do this we use a GradientDrawable.
281ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * The color supplied has an alpha of FF so we first do:
282ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * color & 0x00FFFFFF
283ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * to clear the alpha. Then we add our alpha to it.
284ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * We use 3 colors to get a step effect where it starts off very
285ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * light and quickly becomes dark and then a slow transition to
286ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * be even darker.
287ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         */
288ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        color &= CLEAR_ALPHA_MASK;
289ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int startColor = color | HIGH_ALPHA;
290ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int middleColor = color | MED_ALPHA;
291ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int endColor = color | LOW_ALPHA;
292ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int[] colors = new int[] {startColor, middleColor, endColor};
293ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        GradientDrawable d = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);
294ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        d.setCornerRadii(CORNERS);
295ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        return d;
296ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    }
297ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Formats the given Time object so that it gives the month and year
300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * (for example, "September 2007").
301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param time the time to format
303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the string containing the weekday and the date
304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
305ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan    public static String formatMonthYear(Context context, Time time) {
306ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan        return time.format(context.getResources().getString(R.string.month_year));
307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // TODO: replace this with the correct i18n way to do this
310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final String englishNthDay[] = {
311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        "", "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th",
312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        "10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th",
313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        "20th", "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "29th",
314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        "30th", "31st"
315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    };
316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static String formatNth(int nth) {
318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return "the " + englishNthDay[nth];
319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
322d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang     * Returns a list joined together by the provided delimiter, for example,
323d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang     * ["a", "b", "c"] could be joined into "a,b,c"
324d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang     *
325d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang     * @param things the things to join together
326d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang     * @param delim the delimiter to use
327d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang     * @return a string contained the things joined together
328d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang     */
329d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang    public static String join(List<?> things, String delim) {
330d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang        StringBuilder builder = new StringBuilder();
331d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang        boolean first = true;
332d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang        for (Object thing : things) {
333d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang            if (first) {
334d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang                first = false;
335d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang            } else {
336d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang                builder.append(delim);
337d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang            }
338d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang            builder.append(thing.toString());
339d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang        }
340d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang        return builder.toString();
341d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang    }
342d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang
343d7c7f2ab6fdb55451ead2d54819ba8f37af2d0a7Mason Tang    /**
344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Sets the time to the beginning of the day (midnight) by clearing the
345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * hour, minute, and second fields.
346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    static void setTimeToStartOfDay(Time time) {
348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        time.second = 0;
349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        time.minute = 0;
350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        time.hour = 0;
351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
35256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
35356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    /**
35456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Get first day of week as android.text.format.Time constant.
35556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return the first day of week in android.text.format.Time
35656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
35756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    public static int getFirstDayOfWeek() {
35856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        int startDay = Calendar.getInstance().getFirstDayOfWeek();
35956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        if (startDay == Calendar.SATURDAY) {
36056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.SATURDAY;
36156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        } else if (startDay == Calendar.MONDAY) {
36256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.MONDAY;
36356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        } else {
36456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.SUNDAY;
36556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        }
36656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
36756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
36856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    /**
36956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Determine whether the column position is Saturday or not.
37056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param column the column position
37156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param firstDayOfWeek the first day of week in android.text.format.Time
37256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return true if the column is Saturday position
37356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
37456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    public static boolean isSaturday(int column, int firstDayOfWeek) {
37556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        return (firstDayOfWeek == Time.SUNDAY && column == 6)
37656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.MONDAY && column == 5)
37756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.SATURDAY && column == 0);
37856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
37956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
38056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    /**
38156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Determine whether the column position is Sunday or not.
38256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param column the column position
38356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param firstDayOfWeek the first day of week in android.text.format.Time
38456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return true if the column is Sunday position
38556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
38656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    public static boolean isSunday(int column, int firstDayOfWeek) {
38756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        return (firstDayOfWeek == Time.SUNDAY && column == 0)
38856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.MONDAY && column == 6)
38956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.SATURDAY && column == 1);
39056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
391ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
392ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    /**
393ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * Scan through a cursor of calendars and check if names are duplicated.
394ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     *
395ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * This travels a cursor containing calendar display names and fills in the provided map with
396ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * whether or not each name is repeated.
397ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param isDuplicateName The map to put the duplicate check results in.
398ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param cursor The query of calendars to check
399ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param nameIndex The column of the query that contains the display name
400ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     */
401ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    public static void checkForDuplicateNames(Map<String, Boolean> isDuplicateName, Cursor cursor,
402ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            int nameIndex) {
403ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        isDuplicateName.clear();
404ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        cursor.moveToPosition(-1);
405ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        while (cursor.moveToNext()) {
406ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            String displayName = cursor.getString(nameIndex);
407ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            // Set it to true if we've seen this name before, false otherwise
408ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            if (displayName != null) {
409ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan                isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName));
410ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            }
411ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        }
412ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    }
413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
414