Utils.java revision 3ea333d41c04fd5f3a5d45f540c17894874429e8
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;
27f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tangimport android.content.SharedPreferences.Editor;
28ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.database.Cursor;
29a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErikimport android.database.MatrixCursor;
30ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.graphics.drawable.Drawable;
31ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.graphics.drawable.GradientDrawable;
321ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.net.Uri;
33f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tangimport android.os.AsyncTask;
34d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport android.os.Bundle;
35eb10fa8bee049e0052b5cb53dcfbdaccef9f2740Erikimport android.text.TextUtils;
36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time;
371ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.util.Log;
38146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
3956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashiimport java.util.Calendar;
401ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport java.util.List;
41ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport java.util.Map;
423ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tangimport java.util.TimeZone;
4356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
44146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class Utils {
45bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    // Set to 0 until we have UI to perform undo
46bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    public static final long UNDO_DELAY = 0;
47bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
4879f228124de7d98146ca526d743436f6419e2365Erik    // For recurring events which instances of the series are being modified
4979f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_UNINITIALIZED = 0;
5079f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_SELECTED = 1;
5179f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_ALL_FOLLOWING = 2;
5279f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_ALL = 3;
5379f228124de7d98146ca526d743436f6419e2365Erik
5479f228124de7d98146ca526d743436f6419e2365Erik    // When the edit event view finishes it passes back the appropriate exit code.
5579f228124de7d98146ca526d743436f6419e2365Erik    public static final int DONE_REVERT = 0;
5679f228124de7d98146ca526d743436f6419e2365Erik    public static final int DONE_SAVE = 1;
5779f228124de7d98146ca526d743436f6419e2365Erik    public static final int DONE_DELETE = 2;
5879f228124de7d98146ca526d743436f6419e2365Erik
59ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int CLEAR_ALPHA_MASK = 0x00FFFFFF;
60ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int HIGH_ALPHA = 255 << 24;
61ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int MED_ALPHA = 180 << 24;
62ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    private static final int LOW_ALPHA = 150 << 24;
63ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
64ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    protected static final String OPEN_EMAIL_MARKER = " <";
65ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    protected static final String CLOSE_EMAIL_MARKER = ">";
66ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
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";
73d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
74d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static int getViewTypeFromIntentAndSharedPref(Activity activity) {
75d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        Bundle extras = activity.getIntent().getExtras();
76d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(activity);
77d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
78d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        if (extras != null) {
79d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            if (extras.getBoolean(INTENT_KEY_DETAIL_VIEW, false)) {
80d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                // This is the "detail" view which is either agenda or day view
81d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                return prefs.getInt(CalendarPreferenceActivity.KEY_DETAILED_VIEW,
82d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                        CalendarPreferenceActivity.DEFAULT_DETAILED_VIEW);
83d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            } else if (INTENT_VALUE_VIEW_TYPE_DAY.equals(extras.getString(INTENT_KEY_VIEW_TYPE))) {
84d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                // Not sure who uses this. This logic came from LaunchActivity
85d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                return ViewType.DAY;
86d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            }
87d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        }
88d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
89d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        // Default to the last view
90d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        return prefs.getInt(CalendarPreferenceActivity.KEY_START_VIEW,
91d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                CalendarPreferenceActivity.DEFAULT_START_VIEW);
92d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    }
93ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
94fbce65e53c7a111955f638db5bf8bee35381e5b7Erik    public static String getSharedPreference(Context context, String key, String defaultValue) {
95a17725e24d51b7a6f002dd5afd3270c8eeea0dbeJeff Hamilton        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
9645efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan        return prefs.getString(key, defaultValue);
9745efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan    }
9845efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan
99d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static int getSharedPreference(Context context, String key, int defaultValue) {
100d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
101d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        return prefs.getInt(key, defaultValue);
102d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    }
103d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
104f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang
105f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang    private static class PreferenceCommitTask extends
106f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang            AsyncTask<SharedPreferences.Editor, Integer, Boolean> {
107f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang        @Override
108f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang        protected Boolean doInBackground(Editor... params) {
109f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang            Editor editor = params[0];
110f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang            return editor.commit();
111f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang        }
112f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang    }
113f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang
114f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang    /**
115f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * Commits the given shared preferences editor asynchronously in the
116f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * background.
117f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     *
118f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * @param editor the editor to commit
119f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     */
120f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang    public static void commitSharedPreferencesEditor(Editor editor) {
121f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang        (new PreferenceCommitTask()).execute(editor);
122f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang    }
123f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang
124f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang    /**
125f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * Asynchronously sets the preference with the given key to the given value
126f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     *
127f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * @param context the context to use to get preferences from
128f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * @param key the key of the preference to set
129f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * @param value the value to set
130f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     */
131fbce65e53c7a111955f638db5bf8bee35381e5b7Erik    public static void setSharedPreference(Context context, String key, String value) {
132a17725e24d51b7a6f002dd5afd3270c8eeea0dbeJeff Hamilton        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
133f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang        Editor editor = prefs.edit().putString(key, value);
134f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang        commitSharedPreferencesEditor(editor);
13545efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan    }
13645efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan
137d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    /**
138d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     * Save default agenda/day/week/month view for next time
139d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     *
140d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     * @param context
141d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     * @param viewId {@link CalendarController.ViewType}
142d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     */
143e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan    static void setDefaultView(Context context, int viewId) {
144a17725e24d51b7a6f002dd5afd3270c8eeea0dbeJeff Hamilton        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
145e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        SharedPreferences.Editor editor = prefs.edit();
146f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang
147d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        if (viewId == CalendarController.ViewType.AGENDA
148d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                || viewId == CalendarController.ViewType.DAY) {
149e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan            // Record the (new) detail start view only for Agenda and Day
150d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            editor.putInt(CalendarPreferenceActivity.KEY_DETAILED_VIEW, viewId);
151e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        }
152e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
153e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        // Record the (new) start view
154d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        editor.putInt(CalendarPreferenceActivity.KEY_START_VIEW, viewId);
155f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang
156f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang        commitSharedPreferencesEditor(editor);
157e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan    }
158e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
159a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    public static MatrixCursor matrixCursorFromCursor(Cursor cursor) {
160a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames());
161a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        int numColumns = cursor.getColumnCount();
162a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        String data[] = new String[numColumns];
163a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        cursor.moveToPosition(-1);
164a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        while (cursor.moveToNext()) {
165a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            for (int i = 0; i < numColumns; i++) {
166a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                data[i] = cursor.getString(i);
167a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            }
168a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            newCursor.addRow(data);
169a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
170a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        return newCursor;
171a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    }
172a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
173a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    /**
174a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     * Compares two cursors to see if they contain the same data.
175a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     *
176a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     * @return Returns true of the cursors contain the same data and are not null, false
177a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     * otherwise
178a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     */
179a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    public static boolean compareCursors(Cursor c1, Cursor c2) {
180a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if(c1 == null || c2 == null) {
181a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
182a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
183a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
184a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        int numColumns = c1.getColumnCount();
185a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if (numColumns != c2.getColumnCount()) {
186a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
187a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
188a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
189a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if (c1.getCount() != c2.getCount()) {
190a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
191a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
192a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
193a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        c1.moveToPosition(-1);
194a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        c2.moveToPosition(-1);
195a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        while(c1.moveToNext() && c2.moveToNext()) {
196a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            for(int i = 0; i < numColumns; i++) {
197eb10fa8bee049e0052b5cb53dcfbdaccef9f2740Erik                if(!TextUtils.equals(c1.getString(i), c2.getString(i))) {
198a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                    return false;
199a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                }
200a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            }
201a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
202a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
203a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        return true;
204a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    }
205a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * If the given intent specifies a time (in milliseconds since the epoch),
208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * then that time is returned. Otherwise, the current time is returned.
209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final long timeFromIntentInMillis(Intent intent) {
211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // If the time was specified, then use that.  Otherwise, use the current time.
2121ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        Uri data = intent.getData();
213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long millis = intent.getLongExtra(EVENT_BEGIN_TIME, -1);
2141ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        if (millis == -1 && data != null && data.isHierarchical()) {
2151ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik            List<String> path = data.getPathSegments();
216eca5d33e4230cf6ac3acfe3fabf853f9275f98caErik            if(path.size() == 2 && path.get(0).equals("time")) {
2171ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                try {
2181ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                    millis = Long.valueOf(data.getLastPathSegment());
2191ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                } catch (NumberFormatException e) {
2201ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                    Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time " +
2211ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                            "found. Using current time.");
2221ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                }
2231ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik            }
2241ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        }
22576727b7a9cf780f200414548b9d454bf9a701e3eErik        if (millis <= 0) {
226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            millis = System.currentTimeMillis();
227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return millis;
229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
231ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    public static Drawable getColorChip(int color) {
232ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        /*
233ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * We want the color chip to have a nice gradient using
234ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * the color of the calendar. To do this we use a GradientDrawable.
235ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * The color supplied has an alpha of FF so we first do:
236ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * color & 0x00FFFFFF
237ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * to clear the alpha. Then we add our alpha to it.
238ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * We use 3 colors to get a step effect where it starts off very
239ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * light and quickly becomes dark and then a slow transition to
240ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         * be even darker.
241ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan         */
242ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        color &= CLEAR_ALPHA_MASK;
243ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int startColor = color | HIGH_ALPHA;
244ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int middleColor = color | MED_ALPHA;
245ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int endColor = color | LOW_ALPHA;
246ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        int[] colors = new int[] {startColor, middleColor, endColor};
247ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        GradientDrawable d = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);
248ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        d.setCornerRadii(CORNERS);
249ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        return d;
250ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    }
251ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Formats the given Time object so that it gives the month and year
254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * (for example, "September 2007").
255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param time the time to format
257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the string containing the weekday and the date
258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
259ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan    public static String formatMonthYear(Context context, Time time) {
260ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan        return time.format(context.getResources().getString(R.string.month_year));
261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
2644c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * Returns a list joined together by the provided delimiter, for example,
2654c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * ["a", "b", "c"] could be joined into "a,b,c"
2664c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     *
2674c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * @param things the things to join together
2684c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * @param delim the delimiter to use
2694c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * @return a string contained the things joined together
2704c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     */
2714c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang    public static String join(List<?> things, String delim) {
2724c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        StringBuilder builder = new StringBuilder();
2734c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        boolean first = true;
2744c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        for (Object thing : things) {
2754c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            if (first) {
2764c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang                first = false;
2774c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            } else {
2784c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang                builder.append(delim);
2794c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            }
2804c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            builder.append(thing.toString());
2814c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        }
2824c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        return builder.toString();
2834c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang    }
2844c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang
2854c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang    /**
28656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Get first day of week as android.text.format.Time constant.
28756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return the first day of week in android.text.format.Time
28856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
2898e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang    public static int getFirstDayOfWeek(Context context) {
2908e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
291d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        String pref = prefs.getString(CalendarPreferenceActivity.KEY_WEEK_START_DAY,
2928e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang                CalendarPreferenceActivity.WEEK_START_DEFAULT);
2938e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang
2948e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        int startDay;
2958e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        if (CalendarPreferenceActivity.WEEK_START_DEFAULT.equals(pref)) {
2968e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang            startDay = Calendar.getInstance().getFirstDayOfWeek();
2978e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        } else {
2988e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang            startDay = Integer.parseInt(pref);
2998e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        }
3008e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang
30156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        if (startDay == Calendar.SATURDAY) {
30256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.SATURDAY;
30356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        } else if (startDay == Calendar.MONDAY) {
30456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.MONDAY;
30556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        } else {
30656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.SUNDAY;
30756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        }
30856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
30956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
31056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    /**
31156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Determine whether the column position is Saturday or not.
31256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param column the column position
31356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param firstDayOfWeek the first day of week in android.text.format.Time
31456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return true if the column is Saturday position
31556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
31656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    public static boolean isSaturday(int column, int firstDayOfWeek) {
31756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        return (firstDayOfWeek == Time.SUNDAY && column == 6)
31856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.MONDAY && column == 5)
31956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.SATURDAY && column == 0);
32056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
32156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
32256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    /**
32356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Determine whether the column position is Sunday or not.
32456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param column the column position
32556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param firstDayOfWeek the first day of week in android.text.format.Time
32656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return true if the column is Sunday position
32756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
32856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    public static boolean isSunday(int column, int firstDayOfWeek) {
32956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        return (firstDayOfWeek == Time.SUNDAY && column == 0)
33056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.MONDAY && column == 6)
33156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            || (firstDayOfWeek == Time.SATURDAY && column == 1);
33256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
333ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
334ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    /**
3353ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     * Convert given UTC time into current local time.
3363ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     *
3373ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     * @param recycle Time object to recycle, otherwise null.
3383ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     * @param utcTime Time to convert, in UTC.
3393ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     */
3403ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang    public static long convertUtcToLocal(Time recycle, long utcTime) {
3413ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        if (recycle == null) {
3423ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang            recycle = new Time();
3433ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        }
3443ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        recycle.timezone = Time.TIMEZONE_UTC;
3453ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        recycle.set(utcTime);
3463ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        recycle.timezone = TimeZone.getDefault().getID();
3473ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        return recycle.normalize(true);
3483ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang    }
3493ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang
3503ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang    /**
351ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * Scan through a cursor of calendars and check if names are duplicated.
352ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     *
353ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * This travels a cursor containing calendar display names and fills in the provided map with
354ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * whether or not each name is repeated.
355ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param isDuplicateName The map to put the duplicate check results in.
356ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param cursor The query of calendars to check
357ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param nameIndex The column of the query that contains the display name
358ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     */
359ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    public static void checkForDuplicateNames(Map<String, Boolean> isDuplicateName, Cursor cursor,
360ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            int nameIndex) {
361ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        isDuplicateName.clear();
362ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        cursor.moveToPosition(-1);
363ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        while (cursor.moveToNext()) {
364ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            String displayName = cursor.getString(nameIndex);
365ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            // Set it to true if we've seen this name before, false otherwise
366ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            if (displayName != null) {
367ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan                isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName));
368ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            }
369ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        }
370ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    }
3719138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
3729138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /**
3739138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * Null-safe object comparison
3749138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * @param s1
3759138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * @param s2
3769138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * @return
3779138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     */
3789138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    public static boolean equals(Object o1, Object o2) {
3799138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        return o1 == null ? o2 == null : o1.equals(o2);
3809138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    }
381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
382