Utils.java revision 79f228124de7d98146ca526d743436f6419e2365
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.calendar;
18
19import static android.provider.Calendar.EVENT_BEGIN_TIME;
20
21import android.content.Context;
22import android.content.Intent;
23import android.content.SharedPreferences;
24import android.database.Cursor;
25import android.database.MatrixCursor;
26import android.graphics.drawable.Drawable;
27import android.graphics.drawable.GradientDrawable;
28import android.net.Uri;
29import android.text.TextUtils;
30import android.text.format.Time;
31import android.util.Log;
32import android.view.animation.AlphaAnimation;
33import android.widget.ViewFlipper;
34
35import java.util.Calendar;
36import java.util.List;
37import java.util.Map;
38
39public class Utils {
40    // Set to 0 until we have UI to perform undo
41    public static final long UNDO_DELAY = 0;
42
43    // For recurring events which instances of the series are being modified
44    public static final int MODIFY_UNINITIALIZED = 0;
45    public static final int MODIFY_SELECTED = 1;
46    public static final int MODIFY_ALL_FOLLOWING = 2;
47    public static final int MODIFY_ALL = 3;
48
49    // When the edit event view finishes it passes back the appropriate exit code.
50    public static final int DONE_REVERT = 0;
51    public static final int DONE_SAVE = 1;
52    public static final int DONE_DELETE = 2;
53
54    private static final int CLEAR_ALPHA_MASK = 0x00FFFFFF;
55    private static final int HIGH_ALPHA = 255 << 24;
56    private static final int MED_ALPHA = 180 << 24;
57    private static final int LOW_ALPHA = 150 << 24;
58
59    protected static final String OPEN_EMAIL_MARKER = " <";
60    protected static final String CLOSE_EMAIL_MARKER = ">";
61
62    /* The corner should be rounded on the top right and bottom right */
63    private static final float[] CORNERS = new float[] {0, 0, 5, 5, 5, 5, 0, 0};
64
65
66    public static void startActivity(Context context, String className, long time) {
67        Intent intent = new Intent(Intent.ACTION_VIEW);
68
69        intent.setClassName(context, className);
70        intent.putExtra(EVENT_BEGIN_TIME, time);
71        intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
72
73        context.startActivity(intent);
74    }
75
76    static String getSharedPreference(Context context, String key, String defaultValue) {
77        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
78        return prefs.getString(key, defaultValue);
79    }
80
81    static void setSharedPreference(Context context, String key, String value) {
82        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
83        SharedPreferences.Editor editor = prefs.edit();
84        editor.putString(key, value);
85        editor.commit();
86    }
87
88    static void setDefaultView(Context context, int viewId) {
89        String activityString = CalendarApplication.ACTIVITY_NAMES[viewId];
90
91        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
92        SharedPreferences.Editor editor = prefs.edit();
93        if (viewId == CalendarApplication.AGENDA_VIEW_ID ||
94                viewId == CalendarApplication.DAY_VIEW_ID) {
95            // Record the (new) detail start view only for Agenda and Day
96            editor.putString(CalendarPreferenceActivity.KEY_DETAILED_VIEW, activityString);
97        }
98
99        // Record the (new) start view
100        editor.putString(CalendarPreferenceActivity.KEY_START_VIEW, activityString);
101        editor.commit();
102    }
103
104    public static final Time timeFromIntent(Intent intent) {
105        Time time = new Time();
106        time.set(timeFromIntentInMillis(intent));
107        return time;
108    }
109
110    public static MatrixCursor matrixCursorFromCursor(Cursor cursor) {
111        MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames());
112        int numColumns = cursor.getColumnCount();
113        String data[] = new String[numColumns];
114        cursor.moveToPosition(-1);
115        while (cursor.moveToNext()) {
116            for (int i = 0; i < numColumns; i++) {
117                data[i] = cursor.getString(i);
118            }
119            newCursor.addRow(data);
120        }
121        return newCursor;
122    }
123
124    /**
125     * Compares two cursors to see if they contain the same data.
126     *
127     * @return Returns true of the cursors contain the same data and are not null, false
128     * otherwise
129     */
130    public static boolean compareCursors(Cursor c1, Cursor c2) {
131        if(c1 == null || c2 == null) {
132            return false;
133        }
134
135        int numColumns = c1.getColumnCount();
136        if (numColumns != c2.getColumnCount()) {
137            return false;
138        }
139
140        if (c1.getCount() != c2.getCount()) {
141            return false;
142        }
143
144        c1.moveToPosition(-1);
145        c2.moveToPosition(-1);
146        while(c1.moveToNext() && c2.moveToNext()) {
147            for(int i = 0; i < numColumns; i++) {
148                if(!TextUtils.equals(c1.getString(i), c2.getString(i))) {
149                    return false;
150                }
151            }
152        }
153
154        return true;
155    }
156
157    /**
158     * If the given intent specifies a time (in milliseconds since the epoch),
159     * then that time is returned. Otherwise, the current time is returned.
160     */
161    public static final long timeFromIntentInMillis(Intent intent) {
162        // If the time was specified, then use that.  Otherwise, use the current time.
163        Uri data = intent.getData();
164        long millis = intent.getLongExtra(EVENT_BEGIN_TIME, -1);
165        if (millis == -1 && data != null && data.isHierarchical()) {
166            List<String> path = data.getPathSegments();
167            if(path.size() == 2 && path.get(0).equals("time")) {
168                try {
169                    millis = Long.valueOf(data.getLastPathSegment());
170                } catch (NumberFormatException e) {
171                    Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time " +
172                            "found. Using current time.");
173                }
174            }
175        }
176        if (millis <= 0) {
177            millis = System.currentTimeMillis();
178        }
179        return millis;
180    }
181
182    public static final void applyAlphaAnimation(ViewFlipper v) {
183        AlphaAnimation in = new AlphaAnimation(0.0f, 1.0f);
184
185        in.setStartOffset(0);
186        in.setDuration(500);
187
188        AlphaAnimation out = new AlphaAnimation(1.0f, 0.0f);
189
190        out.setStartOffset(0);
191        out.setDuration(500);
192
193        v.setInAnimation(in);
194        v.setOutAnimation(out);
195    }
196
197    public static Drawable getColorChip(int color) {
198        /*
199         * We want the color chip to have a nice gradient using
200         * the color of the calendar. To do this we use a GradientDrawable.
201         * The color supplied has an alpha of FF so we first do:
202         * color & 0x00FFFFFF
203         * to clear the alpha. Then we add our alpha to it.
204         * We use 3 colors to get a step effect where it starts off very
205         * light and quickly becomes dark and then a slow transition to
206         * be even darker.
207         */
208        color &= CLEAR_ALPHA_MASK;
209        int startColor = color | HIGH_ALPHA;
210        int middleColor = color | MED_ALPHA;
211        int endColor = color | LOW_ALPHA;
212        int[] colors = new int[] {startColor, middleColor, endColor};
213        GradientDrawable d = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);
214        d.setCornerRadii(CORNERS);
215        return d;
216    }
217
218    /**
219     * Formats the given Time object so that it gives the month and year
220     * (for example, "September 2007").
221     *
222     * @param time the time to format
223     * @return the string containing the weekday and the date
224     */
225    public static String formatMonthYear(Context context, Time time) {
226        return time.format(context.getResources().getString(R.string.month_year));
227    }
228
229    /**
230     * Sets the time to the beginning of the day (midnight) by clearing the
231     * hour, minute, and second fields.
232     */
233    static void setTimeToStartOfDay(Time time) {
234        time.second = 0;
235        time.minute = 0;
236        time.hour = 0;
237    }
238
239    /**
240     * Get first day of week as android.text.format.Time constant.
241     * @return the first day of week in android.text.format.Time
242     */
243    public static int getFirstDayOfWeek() {
244        int startDay = Calendar.getInstance().getFirstDayOfWeek();
245        if (startDay == Calendar.SATURDAY) {
246            return Time.SATURDAY;
247        } else if (startDay == Calendar.MONDAY) {
248            return Time.MONDAY;
249        } else {
250            return Time.SUNDAY;
251        }
252    }
253
254    /**
255     * Determine whether the column position is Saturday or not.
256     * @param column the column position
257     * @param firstDayOfWeek the first day of week in android.text.format.Time
258     * @return true if the column is Saturday position
259     */
260    public static boolean isSaturday(int column, int firstDayOfWeek) {
261        return (firstDayOfWeek == Time.SUNDAY && column == 6)
262            || (firstDayOfWeek == Time.MONDAY && column == 5)
263            || (firstDayOfWeek == Time.SATURDAY && column == 0);
264    }
265
266    /**
267     * Determine whether the column position is Sunday or not.
268     * @param column the column position
269     * @param firstDayOfWeek the first day of week in android.text.format.Time
270     * @return true if the column is Sunday position
271     */
272    public static boolean isSunday(int column, int firstDayOfWeek) {
273        return (firstDayOfWeek == Time.SUNDAY && column == 0)
274            || (firstDayOfWeek == Time.MONDAY && column == 6)
275            || (firstDayOfWeek == Time.SATURDAY && column == 1);
276    }
277
278    /**
279     * Scan through a cursor of calendars and check if names are duplicated.
280     *
281     * This travels a cursor containing calendar display names and fills in the provided map with
282     * whether or not each name is repeated.
283     * @param isDuplicateName The map to put the duplicate check results in.
284     * @param cursor The query of calendars to check
285     * @param nameIndex The column of the query that contains the display name
286     */
287    public static void checkForDuplicateNames(Map<String, Boolean> isDuplicateName, Cursor cursor,
288            int nameIndex) {
289        isDuplicateName.clear();
290        cursor.moveToPosition(-1);
291        while (cursor.moveToNext()) {
292            String displayName = cursor.getString(nameIndex);
293            // Set it to true if we've seen this name before, false otherwise
294            if (displayName != null) {
295                isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName));
296            }
297        }
298    }
299}
300