Utils.java revision dc75d7711c7786e3a0c0752d6dca4dbc3e63895b
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    private static final int CLEAR_ALPHA_MASK = 0x00FFFFFF;
44    private static final int HIGH_ALPHA = 255 << 24;
45    private static final int MED_ALPHA = 180 << 24;
46    private static final int LOW_ALPHA = 150 << 24;
47
48    protected static final String OPEN_EMAIL_MARKER = " <";
49    protected static final String CLOSE_EMAIL_MARKER = ">";
50
51    /* The corner should be rounded on the top right and bottom right */
52    private static final float[] CORNERS = new float[] {0, 0, 5, 5, 5, 5, 0, 0};
53
54
55    public static void startActivity(Context context, String className, long time) {
56        Intent intent = new Intent(Intent.ACTION_VIEW);
57
58        intent.setClassName(context, className);
59        intent.putExtra(EVENT_BEGIN_TIME, time);
60        intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
61
62        context.startActivity(intent);
63    }
64
65    static String getSharedPreference(Context context, String key, String defaultValue) {
66        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
67        return prefs.getString(key, defaultValue);
68    }
69
70    static void setSharedPreference(Context context, String key, String value) {
71        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
72        SharedPreferences.Editor editor = prefs.edit();
73        editor.putString(key, value);
74        editor.commit();
75    }
76
77    static void setDefaultView(Context context, int viewId) {
78        String activityString = CalendarApplication.ACTIVITY_NAMES[viewId];
79
80        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context);
81        SharedPreferences.Editor editor = prefs.edit();
82        if (viewId == CalendarApplication.AGENDA_VIEW_ID ||
83                viewId == CalendarApplication.DAY_VIEW_ID) {
84            // Record the (new) detail start view only for Agenda and Day
85            editor.putString(CalendarPreferenceActivity.KEY_DETAILED_VIEW, activityString);
86        }
87
88        // Record the (new) start view
89        editor.putString(CalendarPreferenceActivity.KEY_START_VIEW, activityString);
90        editor.commit();
91    }
92
93    public static final Time timeFromIntent(Intent intent) {
94        Time time = new Time();
95        time.set(timeFromIntentInMillis(intent));
96        return time;
97    }
98
99    public static MatrixCursor matrixCursorFromCursor(Cursor cursor) {
100        MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames());
101        int numColumns = cursor.getColumnCount();
102        String data[] = new String[numColumns];
103        cursor.moveToPosition(-1);
104        while (cursor.moveToNext()) {
105            for (int i = 0; i < numColumns; i++) {
106                data[i] = cursor.getString(i);
107            }
108            newCursor.addRow(data);
109        }
110        return newCursor;
111    }
112
113    /**
114     * Compares two cursors to see if they contain the same data.
115     *
116     * @return Returns true of the cursors contain the same data and are not null, false
117     * otherwise
118     */
119    public static boolean compareCursors(Cursor c1, Cursor c2) {
120        if(c1 == null || c2 == null) {
121            return false;
122        }
123
124        int numColumns = c1.getColumnCount();
125        if (numColumns != c2.getColumnCount()) {
126            return false;
127        }
128
129        if (c1.getCount() != c2.getCount()) {
130            return false;
131        }
132
133        c1.moveToPosition(-1);
134        c2.moveToPosition(-1);
135        while(c1.moveToNext() && c2.moveToNext()) {
136            for(int i = 0; i < numColumns; i++) {
137                if(!TextUtils.equals(c1.getString(i), c2.getString(i))) {
138                    return false;
139                }
140            }
141        }
142
143        return true;
144    }
145
146    /**
147     * If the given intent specifies a time (in milliseconds since the epoch),
148     * then that time is returned. Otherwise, the current time is returned.
149     */
150    public static final long timeFromIntentInMillis(Intent intent) {
151        // If the time was specified, then use that.  Otherwise, use the current time.
152        Uri data = intent.getData();
153        long millis = intent.getLongExtra(EVENT_BEGIN_TIME, -1);
154        if (millis == -1 && data != null && data.isHierarchical()) {
155            List<String> path = data.getPathSegments();
156            if(path.size() == 2 && path.get(0).equals("time")) {
157                try {
158                    millis = Long.valueOf(data.getLastPathSegment());
159                } catch (NumberFormatException e) {
160                    Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time " +
161                            "found. Using current time.");
162                }
163            }
164        }
165        if (millis <= 0) {
166            millis = System.currentTimeMillis();
167        }
168        return millis;
169    }
170
171    public static final void applyAlphaAnimation(ViewFlipper v) {
172        AlphaAnimation in = new AlphaAnimation(0.0f, 1.0f);
173
174        in.setStartOffset(0);
175        in.setDuration(500);
176
177        AlphaAnimation out = new AlphaAnimation(1.0f, 0.0f);
178
179        out.setStartOffset(0);
180        out.setDuration(500);
181
182        v.setInAnimation(in);
183        v.setOutAnimation(out);
184    }
185
186    public static Drawable getColorChip(int color) {
187        /*
188         * We want the color chip to have a nice gradient using
189         * the color of the calendar. To do this we use a GradientDrawable.
190         * The color supplied has an alpha of FF so we first do:
191         * color & 0x00FFFFFF
192         * to clear the alpha. Then we add our alpha to it.
193         * We use 3 colors to get a step effect where it starts off very
194         * light and quickly becomes dark and then a slow transition to
195         * be even darker.
196         */
197        color &= CLEAR_ALPHA_MASK;
198        int startColor = color | HIGH_ALPHA;
199        int middleColor = color | MED_ALPHA;
200        int endColor = color | LOW_ALPHA;
201        int[] colors = new int[] {startColor, middleColor, endColor};
202        GradientDrawable d = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);
203        d.setCornerRadii(CORNERS);
204        return d;
205    }
206
207    /**
208     * Formats the given Time object so that it gives the month and year
209     * (for example, "September 2007").
210     *
211     * @param time the time to format
212     * @return the string containing the weekday and the date
213     */
214    public static String formatMonthYear(Context context, Time time) {
215        return time.format(context.getResources().getString(R.string.month_year));
216    }
217
218    /**
219     * Sets the time to the beginning of the day (midnight) by clearing the
220     * hour, minute, and second fields.
221     */
222    static void setTimeToStartOfDay(Time time) {
223        time.second = 0;
224        time.minute = 0;
225        time.hour = 0;
226    }
227
228    /**
229     * Get first day of week as android.text.format.Time constant.
230     * @return the first day of week in android.text.format.Time
231     */
232    public static int getFirstDayOfWeek() {
233        int startDay = Calendar.getInstance().getFirstDayOfWeek();
234        if (startDay == Calendar.SATURDAY) {
235            return Time.SATURDAY;
236        } else if (startDay == Calendar.MONDAY) {
237            return Time.MONDAY;
238        } else {
239            return Time.SUNDAY;
240        }
241    }
242
243    /**
244     * Determine whether the column position is Saturday or not.
245     * @param column the column position
246     * @param firstDayOfWeek the first day of week in android.text.format.Time
247     * @return true if the column is Saturday position
248     */
249    public static boolean isSaturday(int column, int firstDayOfWeek) {
250        return (firstDayOfWeek == Time.SUNDAY && column == 6)
251            || (firstDayOfWeek == Time.MONDAY && column == 5)
252            || (firstDayOfWeek == Time.SATURDAY && column == 0);
253    }
254
255    /**
256     * Determine whether the column position is Sunday or not.
257     * @param column the column position
258     * @param firstDayOfWeek the first day of week in android.text.format.Time
259     * @return true if the column is Sunday position
260     */
261    public static boolean isSunday(int column, int firstDayOfWeek) {
262        return (firstDayOfWeek == Time.SUNDAY && column == 0)
263            || (firstDayOfWeek == Time.MONDAY && column == 6)
264            || (firstDayOfWeek == Time.SATURDAY && column == 1);
265    }
266
267    /**
268     * Scan through a cursor of calendars and check if names are duplicated.
269     *
270     * This travels a cursor containing calendar display names and fills in the provided map with
271     * whether or not each name is repeated.
272     * @param isDuplicateName The map to put the duplicate check results in.
273     * @param cursor The query of calendars to check
274     * @param nameIndex The column of the query that contains the display name
275     */
276    public static void checkForDuplicateNames(Map<String, Boolean> isDuplicateName, Cursor cursor,
277            int nameIndex) {
278        isDuplicateName.clear();
279        cursor.moveToPosition(-1);
280        while (cursor.moveToNext()) {
281            String displayName = cursor.getString(nameIndex);
282            // Set it to true if we've seen this name before, false otherwise
283            if (displayName != null) {
284                isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName));
285            }
286        }
287    }
288}
289