Utils.java revision 275232dae58bb24e3360a779ada9d24601a99bcf
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
21d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport com.android.calendar.CalendarController.ViewType;
22d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
23d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport android.app.Activity;
24146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context;
25146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Intent;
26e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chanimport android.content.SharedPreferences;
27ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.database.Cursor;
28a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErikimport android.database.MatrixCursor;
29ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.graphics.drawable.Drawable;
30ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.graphics.drawable.GradientDrawable;
311ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.net.Uri;
32d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport android.os.Bundle;
33eb10fa8bee049e0052b5cb53dcfbdaccef9f2740Erikimport android.text.TextUtils;
34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time;
351ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.util.Log;
36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
3756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashiimport java.util.Calendar;
38235d59cf61769ec8ab777d81cd1ceb2e7530f439Erikimport java.util.HashSet;
391ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport java.util.List;
40ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport java.util.Map;
413ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tangimport java.util.TimeZone;
4256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class Utils {
443dc5e908a825b879978ba523d9099dc2255da9a5Erik    private static final boolean DEBUG = true;
453dc5e908a825b879978ba523d9099dc2255da9a5Erik    private static final String TAG = "CalUtils";
46bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    // Set to 0 until we have UI to perform undo
47bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    public static final long UNDO_DELAY = 0;
48bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
4979f228124de7d98146ca526d743436f6419e2365Erik    // For recurring events which instances of the series are being modified
5079f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_UNINITIALIZED = 0;
5179f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_SELECTED = 1;
5279f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_ALL_FOLLOWING = 2;
5379f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_ALL = 3;
5479f228124de7d98146ca526d743436f6419e2365Erik
5579f228124de7d98146ca526d743436f6419e2365Erik    // When the edit event view finishes it passes back the appropriate exit code.
5679f228124de7d98146ca526d743436f6419e2365Erik    public static final int DONE_REVERT = 0;
5779f228124de7d98146ca526d743436f6419e2365Erik    public static final int DONE_SAVE = 1;
5879f228124de7d98146ca526d743436f6419e2365Erik    public static final int DONE_DELETE = 2;
5979f228124de7d98146ca526d743436f6419e2365Erik
60ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int CLEAR_ALPHA_MASK = 0x00FFFFFF;
61ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int HIGH_ALPHA = 255 << 24;
62ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int MED_ALPHA = 180 << 24;
63ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int LOW_ALPHA = 150 << 24;
64ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
65ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    protected static final String OPEN_EMAIL_MARKER = " <";
66ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    protected static final String CLOSE_EMAIL_MARKER = ">";
67ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    /* The corner should be rounded on the top right and bottom right */
68ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final float[] CORNERS = new float[] {0, 0, 5, 5, 5, 5, 0, 0};
69ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
70d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static final String INTENT_KEY_DETAIL_VIEW = "DETAIL_VIEW";
71d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static final String INTENT_KEY_VIEW_TYPE = "VIEW";
72d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static final String INTENT_VALUE_VIEW_TYPE_DAY = "DAY";
73275232dae58bb24e3360a779ada9d24601a99bcfErik
74235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    private volatile static boolean mFirstTZRequest = true;
75235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    private volatile static boolean mTZQueryInProgress = false;
76235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik
77235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    private volatile static boolean mUseHomeTZ = false;
78235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    private volatile static String mHomeTZ = Time.getCurrentTimezone();
79235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik
80235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    private static HashSet<Runnable> mTZCallbacks = new HashSet<Runnable>();
81d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
82d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static int getViewTypeFromIntentAndSharedPref(Activity activity) {
83dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        Intent intent = activity.getIntent();
84dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        Bundle extras = intent.getExtras();
85d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(activity);
86d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
87dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        if (TextUtils.equals(intent.getAction(),Intent.ACTION_EDIT)) {
88dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            return ViewType.EDIT;
89dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        }
90d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        if (extras != null) {
91d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            if (extras.getBoolean(INTENT_KEY_DETAIL_VIEW, false)) {
92d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                // This is the "detail" view which is either agenda or day view
93d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                return prefs.getInt(CalendarPreferenceActivity.KEY_DETAILED_VIEW,
94d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                        CalendarPreferenceActivity.DEFAULT_DETAILED_VIEW);
95d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            } else if (INTENT_VALUE_VIEW_TYPE_DAY.equals(extras.getString(INTENT_KEY_VIEW_TYPE))) {
96d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                // Not sure who uses this. This logic came from LaunchActivity
97d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                return ViewType.DAY;
98d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            }
99d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        }
100d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
101d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        // Default to the last view
102d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        return prefs.getInt(CalendarPreferenceActivity.KEY_START_VIEW,
103d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                CalendarPreferenceActivity.DEFAULT_START_VIEW);
104d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    }
105ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
106235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    /**
1073dc5e908a825b879978ba523d9099dc2255da9a5Erik     * Writes a new home time zone to the db.
1083dc5e908a825b879978ba523d9099dc2255da9a5Erik     *
1093dc5e908a825b879978ba523d9099dc2255da9a5Erik     * Updates the home time zone in the db asynchronously and updates
1103dc5e908a825b879978ba523d9099dc2255da9a5Erik     * the local cache. Sending a time zone of **tbd** will cause it to
1113dc5e908a825b879978ba523d9099dc2255da9a5Erik     * be set to the device's time zone. null or empty tz will be ignored.
1123dc5e908a825b879978ba523d9099dc2255da9a5Erik     *
1133dc5e908a825b879978ba523d9099dc2255da9a5Erik     * @param context The calling activity
1143dc5e908a825b879978ba523d9099dc2255da9a5Erik     * @param timeZone The time zone to set Calendar to, or **tbd**
1153dc5e908a825b879978ba523d9099dc2255da9a5Erik     */
1163dc5e908a825b879978ba523d9099dc2255da9a5Erik    public static void setTimeZone(Context context, String timeZone) {
1173dc5e908a825b879978ba523d9099dc2255da9a5Erik        if (TextUtils.isEmpty(timeZone)) {
1183dc5e908a825b879978ba523d9099dc2255da9a5Erik            if (DEBUG) {
1193dc5e908a825b879978ba523d9099dc2255da9a5Erik                Log.d(TAG, "Empty time zone, nothing to be done.");
1203dc5e908a825b879978ba523d9099dc2255da9a5Erik            }
1213dc5e908a825b879978ba523d9099dc2255da9a5Erik            return;
1223dc5e908a825b879978ba523d9099dc2255da9a5Erik        }
1233dc5e908a825b879978ba523d9099dc2255da9a5Erik        synchronized (mTZCallbacks) {
1243dc5e908a825b879978ba523d9099dc2255da9a5Erik            if (CalendarPreferenceActivity.LOCAL_TZ.equals(timeZone)) {
1253dc5e908a825b879978ba523d9099dc2255da9a5Erik                if (!mUseHomeTZ) {
1263dc5e908a825b879978ba523d9099dc2255da9a5Erik                    return;
1273dc5e908a825b879978ba523d9099dc2255da9a5Erik                }
1283dc5e908a825b879978ba523d9099dc2255da9a5Erik                mUseHomeTZ = false;
1293dc5e908a825b879978ba523d9099dc2255da9a5Erik            } else {
1303dc5e908a825b879978ba523d9099dc2255da9a5Erik                if (TextUtils.equals(mHomeTZ, timeZone)) {
1313dc5e908a825b879978ba523d9099dc2255da9a5Erik                    return;
1323dc5e908a825b879978ba523d9099dc2255da9a5Erik                }
1333dc5e908a825b879978ba523d9099dc2255da9a5Erik                mUseHomeTZ = true;
1343dc5e908a825b879978ba523d9099dc2255da9a5Erik                mHomeTZ = timeZone;
1353dc5e908a825b879978ba523d9099dc2255da9a5Erik            }
1363dc5e908a825b879978ba523d9099dc2255da9a5Erik        }
1373dc5e908a825b879978ba523d9099dc2255da9a5Erik        setSharedPreference(context, CalendarPreferenceActivity.KEY_HOME_TZ_ENABLED, mUseHomeTZ);
1383dc5e908a825b879978ba523d9099dc2255da9a5Erik        if (mUseHomeTZ) {
1393dc5e908a825b879978ba523d9099dc2255da9a5Erik            setSharedPreference(context, CalendarPreferenceActivity.KEY_HOME_TZ, mHomeTZ);
1403dc5e908a825b879978ba523d9099dc2255da9a5Erik        }
1413dc5e908a825b879978ba523d9099dc2255da9a5Erik        // TODO async update db
1423dc5e908a825b879978ba523d9099dc2255da9a5Erik    }
1433dc5e908a825b879978ba523d9099dc2255da9a5Erik
1443dc5e908a825b879978ba523d9099dc2255da9a5Erik    /**
145235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * Gets the time zone that Calendar should be displayed in
146235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     *
147235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * This is a helper method to get the appropriate time zone for Calendar. If this
148235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * is the first time this method has been called it will initiate an asynchronous
149235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * query to verify that the data in preferences is correct. The callback supplied
150235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * will only be called if this query returns a value other than what is stored in
151235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * preferences and should cause the calling activity to refresh anything that
152235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * depends on calling this method.
153235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     *
154235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * @param context The calling activity
155235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * @param callback The runnable that should execute if a query returns new values
156235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * @return The string value representing the time zone Calendar should display
157235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     */
158235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    public static String getTimeZone(Context context, Runnable callback) {
159235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik        synchronized (mTZCallbacks){
160235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik            if (mFirstTZRequest) {
161235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mTZQueryInProgress = true;
162235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mFirstTZRequest = false;
163235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik
164235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
165235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mUseHomeTZ = prefs.getBoolean(
166235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                        CalendarPreferenceActivity.KEY_HOME_TZ_ENABLED, false);
167235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mHomeTZ = prefs.getString(
168235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                        CalendarPreferenceActivity.KEY_HOME_TZ, Time.getCurrentTimezone());
169235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // TODO kick off async query
170235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // When the async query returns it should synchronize on
171235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // mTZCallbacks, update mUseHomeTZ, mHomeTZ, and the
172235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // preferences, set mTZQueryInProgress to false, and call all
173235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // the runnables in mTZCallbacks.
174235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                // TODO remove this line when we have a query
175235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mTZQueryInProgress = false;
176235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik            }
177235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik            if (mTZQueryInProgress) {
178235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik                mTZCallbacks.add(callback);
179235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik            }
180235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik        }
181235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik        return mUseHomeTZ ? mHomeTZ : Time.getCurrentTimezone();
182235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    }
183235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik
184fbce65e53c7a111955f638db5bf8bee35381e5b7Erik    public static String getSharedPreference(Context context, String key, String defaultValue) {
185a17725e24d51b7a6f002dd5afd3270c8eeea0dbeJeff Hamilton        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
18645efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan        return prefs.getString(key, defaultValue);
18745efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan    }
18845efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan
189d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static int getSharedPreference(Context context, String key, int defaultValue) {
190d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
191d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        return prefs.getInt(key, defaultValue);
192d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    }
193d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
194f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang    /**
195f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * Asynchronously sets the preference with the given key to the given value
196f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     *
197f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * @param context the context to use to get preferences from
198f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * @param key the key of the preference to set
199f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * @param value the value to set
200f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     */
201fbce65e53c7a111955f638db5bf8bee35381e5b7Erik    public static void setSharedPreference(Context context, String key, String value) {
202a17725e24d51b7a6f002dd5afd3270c8eeea0dbeJeff Hamilton        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
20324fac46d6b87ce21d5e6a4b1c0fdcaa83d408997Brad Fitzpatrick        prefs.edit().putString(key, value).apply();
20445efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan    }
20545efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan
2063dc5e908a825b879978ba523d9099dc2255da9a5Erik    static void setSharedPreference(Context context, String key, boolean value) {
2073dc5e908a825b879978ba523d9099dc2255da9a5Erik        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
2083dc5e908a825b879978ba523d9099dc2255da9a5Erik        SharedPreferences.Editor editor = prefs.edit();
2093dc5e908a825b879978ba523d9099dc2255da9a5Erik        editor.putBoolean(key, value);
210275232dae58bb24e3360a779ada9d24601a99bcfErik        editor.apply();
2113dc5e908a825b879978ba523d9099dc2255da9a5Erik    }
2123dc5e908a825b879978ba523d9099dc2255da9a5Erik
213d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    /**
214d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     * Save default agenda/day/week/month view for next time
215d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     *
216d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     * @param context
217d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     * @param viewId {@link CalendarController.ViewType}
218d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     */
219e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan    static void setDefaultView(Context context, int viewId) {
220a17725e24d51b7a6f002dd5afd3270c8eeea0dbeJeff Hamilton        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
221e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        SharedPreferences.Editor editor = prefs.edit();
222f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang
223d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        if (viewId == CalendarController.ViewType.AGENDA
224d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                || viewId == CalendarController.ViewType.DAY) {
225e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan            // Record the (new) detail start view only for Agenda and Day
226d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            editor.putInt(CalendarPreferenceActivity.KEY_DETAILED_VIEW, viewId);
227e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        }
228e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
229e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        // Record the (new) start view
230d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        editor.putInt(CalendarPreferenceActivity.KEY_START_VIEW, viewId);
23124fac46d6b87ce21d5e6a4b1c0fdcaa83d408997Brad Fitzpatrick        editor.apply();
232e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan    }
233e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
234a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    public static MatrixCursor matrixCursorFromCursor(Cursor cursor) {
235a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames());
236a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        int numColumns = cursor.getColumnCount();
237a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        String data[] = new String[numColumns];
238a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        cursor.moveToPosition(-1);
239a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        while (cursor.moveToNext()) {
240a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            for (int i = 0; i < numColumns; i++) {
241a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                data[i] = cursor.getString(i);
242a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            }
243a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            newCursor.addRow(data);
244a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
245a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        return newCursor;
246a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    }
247a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
248a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    /**
249a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     * Compares two cursors to see if they contain the same data.
250a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     *
251a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     * @return Returns true of the cursors contain the same data and are not null, false
252a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     * otherwise
253a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     */
254a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    public static boolean compareCursors(Cursor c1, Cursor c2) {
255a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if(c1 == null || c2 == null) {
256a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
257a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
258a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
259a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        int numColumns = c1.getColumnCount();
260a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if (numColumns != c2.getColumnCount()) {
261a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
262a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
263a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
264a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if (c1.getCount() != c2.getCount()) {
265a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
266a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
267a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
268a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        c1.moveToPosition(-1);
269a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        c2.moveToPosition(-1);
270a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        while(c1.moveToNext() && c2.moveToNext()) {
271a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            for(int i = 0; i < numColumns; i++) {
272eb10fa8bee049e0052b5cb53dcfbdaccef9f2740Erik                if(!TextUtils.equals(c1.getString(i), c2.getString(i))) {
273a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                    return false;
274a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                }
275a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            }
276a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
277a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
278a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        return true;
279a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    }
280a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * If the given intent specifies a time (in milliseconds since the epoch),
283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * then that time is returned. Otherwise, the current time is returned.
284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final long timeFromIntentInMillis(Intent intent) {
286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // If the time was specified, then use that.  Otherwise, use the current time.
2871ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        Uri data = intent.getData();
288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long millis = intent.getLongExtra(EVENT_BEGIN_TIME, -1);
2891ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        if (millis == -1 && data != null && data.isHierarchical()) {
2901ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik            List<String> path = data.getPathSegments();
291eca5d33e4230cf6ac3acfe3fabf853f9275f98caErik            if(path.size() == 2 && path.get(0).equals("time")) {
2921ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                try {
2931ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                    millis = Long.valueOf(data.getLastPathSegment());
2941ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                } catch (NumberFormatException e) {
2951ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                    Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time " +
2961ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                            "found. Using current time.");
2971ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                }
2981ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik            }
2991ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        }
30076727b7a9cf780f200414548b9d454bf9a701e3eErik        if (millis <= 0) {
301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            millis = System.currentTimeMillis();
302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return millis;
304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
306ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    public static Drawable getColorChip(int color) {
307ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        /*
308ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * We want the color chip to have a nice gradient using
309ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * the color of the calendar. To do this we use a GradientDrawable.
310ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * The color supplied has an alpha of FF so we first do:
311ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * color & 0x00FFFFFF
312ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * to clear the alpha. Then we add our alpha to it.
313ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * We use 3 colors to get a step effect where it starts off very
314ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * light and quickly becomes dark and then a slow transition to
315ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * be even darker.
316ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         */
317ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        color &= CLEAR_ALPHA_MASK;
318ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int startColor = color | HIGH_ALPHA;
319ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int middleColor = color | MED_ALPHA;
320ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int endColor = color | LOW_ALPHA;
321ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int[] colors = new int[] {startColor, middleColor, endColor};
322ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        GradientDrawable d = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);
323ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        d.setCornerRadii(CORNERS);
324ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        return d;
325ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    }
326ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Formats the given Time object so that it gives the month and year
329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * (for example, "September 2007").
330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param time the time to format
332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the string containing the weekday and the date
333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
334ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan    public static String formatMonthYear(Context context, Time time) {
335ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan        return time.format(context.getResources().getString(R.string.month_year));
336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
3394c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * Returns a list joined together by the provided delimiter, for example,
3404c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * ["a", "b", "c"] could be joined into "a,b,c"
3414c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     *
3424c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * @param things the things to join together
3434c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * @param delim the delimiter to use
3444c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * @return a string contained the things joined together
3454c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     */
3464c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang    public static String join(List<?> things, String delim) {
3474c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        StringBuilder builder = new StringBuilder();
3484c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        boolean first = true;
3494c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        for (Object thing : things) {
3504c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            if (first) {
3514c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang                first = false;
3524c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            } else {
3534c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang                builder.append(delim);
3544c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            }
3554c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            builder.append(thing.toString());
3564c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        }
3574c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        return builder.toString();
3584c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang    }
3594c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang
3604c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang    /**
36156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Get first day of week as android.text.format.Time constant.
36256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return the first day of week in android.text.format.Time
36356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
3648e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang    public static int getFirstDayOfWeek(Context context) {
3658e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
366d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        String pref = prefs.getString(CalendarPreferenceActivity.KEY_WEEK_START_DAY,
3678e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang                CalendarPreferenceActivity.WEEK_START_DEFAULT);
3688e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang
3698e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        int startDay;
3708e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        if (CalendarPreferenceActivity.WEEK_START_DEFAULT.equals(pref)) {
3718e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang            startDay = Calendar.getInstance().getFirstDayOfWeek();
3728e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        } else {
3738e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang            startDay = Integer.parseInt(pref);
3748e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        }
3758e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang
37656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        if (startDay == Calendar.SATURDAY) {
37756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.SATURDAY;
37856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        } else if (startDay == Calendar.MONDAY) {
37956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.MONDAY;
38056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        } else {
38156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.SUNDAY;
38256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        }
38356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
38456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
38556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    /**
38656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Determine whether the column position is Saturday or not.
38756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param column the column position
38856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param firstDayOfWeek the first day of week in android.text.format.Time
38956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return true if the column is Saturday position
39056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
39156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    public static boolean isSaturday(int column, int firstDayOfWeek) {
39256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        return (firstDayOfWeek == Time.SUNDAY && column == 6)
39356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.MONDAY && column == 5)
39456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.SATURDAY && column == 0);
39556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
39656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
39756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    /**
39856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Determine whether the column position is Sunday or not.
39956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param column the column position
40056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param firstDayOfWeek the first day of week in android.text.format.Time
40156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return true if the column is Sunday position
40256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
40356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    public static boolean isSunday(int column, int firstDayOfWeek) {
40456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        return (firstDayOfWeek == Time.SUNDAY && column == 0)
40556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.MONDAY && column == 6)
40656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.SATURDAY && column == 1);
40756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
408ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
409ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    /**
4103ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     * Convert given UTC time into current local time.
4113ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     *
4123ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     * @param recycle Time object to recycle, otherwise null.
4133ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     * @param utcTime Time to convert, in UTC.
4143ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     */
4153ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang    public static long convertUtcToLocal(Time recycle, long utcTime) {
4163ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        if (recycle == null) {
4173ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang            recycle = new Time();
4183ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        }
4193ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        recycle.timezone = Time.TIMEZONE_UTC;
4203ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        recycle.set(utcTime);
4213ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        recycle.timezone = TimeZone.getDefault().getID();
4223ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        return recycle.normalize(true);
4233ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang    }
4243ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang
4253ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang    /**
426ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * Scan through a cursor of calendars and check if names are duplicated.
427ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     *
428ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * This travels a cursor containing calendar display names and fills in the provided map with
429ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * whether or not each name is repeated.
430ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param isDuplicateName The map to put the duplicate check results in.
431ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param cursor The query of calendars to check
432ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param nameIndex The column of the query that contains the display name
433ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     */
434ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    public static void checkForDuplicateNames(Map<String, Boolean> isDuplicateName, Cursor cursor,
435ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            int nameIndex) {
436ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        isDuplicateName.clear();
437ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        cursor.moveToPosition(-1);
438ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        while (cursor.moveToNext()) {
439ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            String displayName = cursor.getString(nameIndex);
440ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            // Set it to true if we've seen this name before, false otherwise
441ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            if (displayName != null) {
442ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan                isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName));
443ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            }
444ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        }
445ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    }
4469138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
4479138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /**
4489138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * Null-safe object comparison
4499138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * @param s1
4509138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * @param s2
4519138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * @return
4529138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     */
4539138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    public static boolean equals(Object o1, Object o2) {
4549138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        return o1 == null ? o2 == null : o1.equals(o2);
4559138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    }
456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
457