Utils.java revision 4c8871bf5dee3b3586b375aee98effde31b781a8
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 com.android.calendar.CalendarController.ViewType; 22 23import android.app.Activity; 24import android.content.Context; 25import android.content.Intent; 26import android.content.SharedPreferences; 27import android.database.Cursor; 28import android.database.MatrixCursor; 29import android.graphics.drawable.Drawable; 30import android.graphics.drawable.GradientDrawable; 31import android.net.Uri; 32import android.os.Bundle; 33import android.text.TextUtils; 34import android.text.format.Time; 35import android.util.Log; 36 37import java.util.Calendar; 38import java.util.List; 39import java.util.Map; 40 41public class Utils { 42 // Set to 0 until we have UI to perform undo 43 public static final long UNDO_DELAY = 0; 44 45 // For recurring events which instances of the series are being modified 46 public static final int MODIFY_UNINITIALIZED = 0; 47 public static final int MODIFY_SELECTED = 1; 48 public static final int MODIFY_ALL_FOLLOWING = 2; 49 public static final int MODIFY_ALL = 3; 50 51 // When the edit event view finishes it passes back the appropriate exit code. 52 public static final int DONE_REVERT = 0; 53 public static final int DONE_SAVE = 1; 54 public static final int DONE_DELETE = 2; 55 56 private static final int CLEAR_ALPHA_MASK = 0x00FFFFFF; 57 private static final int HIGH_ALPHA = 255 << 24; 58 private static final int MED_ALPHA = 180 << 24; 59 private static final int LOW_ALPHA = 150 << 24; 60 61 protected static final String OPEN_EMAIL_MARKER = " <"; 62 protected static final String CLOSE_EMAIL_MARKER = ">"; 63 64 /* The corner should be rounded on the top right and bottom right */ 65 private static final float[] CORNERS = new float[] {0, 0, 5, 5, 5, 5, 0, 0}; 66 67 public static final String INTENT_KEY_DETAIL_VIEW = "DETAIL_VIEW"; 68 public static final String INTENT_KEY_VIEW_TYPE = "VIEW"; 69 public static final String INTENT_VALUE_VIEW_TYPE_DAY = "DAY"; 70 71 public static int getViewTypeFromIntentAndSharedPref(Activity activity) { 72 Bundle extras = activity.getIntent().getExtras(); 73 SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(activity); 74 75 if (extras != null) { 76 if (extras.getBoolean(INTENT_KEY_DETAIL_VIEW, false)) { 77 // This is the "detail" view which is either agenda or day view 78 return prefs.getInt(CalendarPreferenceActivity.KEY_DETAILED_VIEW, 79 CalendarPreferenceActivity.DEFAULT_DETAILED_VIEW); 80 } else if (INTENT_VALUE_VIEW_TYPE_DAY.equals(extras.getString(INTENT_KEY_VIEW_TYPE))) { 81 // Not sure who uses this. This logic came from LaunchActivity 82 return ViewType.DAY; 83 } 84 } 85 86 // Default to the last view 87 return prefs.getInt(CalendarPreferenceActivity.KEY_START_VIEW, 88 CalendarPreferenceActivity.DEFAULT_START_VIEW); 89 } 90 91 static String getSharedPreference(Context context, String key, String defaultValue) { 92 SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context); 93 return prefs.getString(key, defaultValue); 94 } 95 96 public static int getSharedPreference(Context context, String key, int defaultValue) { 97 SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context); 98 return prefs.getInt(key, defaultValue); 99 } 100 101 static void setSharedPreference(Context context, String key, String value) { 102 SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context); 103 SharedPreferences.Editor editor = prefs.edit(); 104 editor.putString(key, value); 105 editor.commit(); 106 } 107 108 /** 109 * Save default agenda/day/week/month view for next time 110 * 111 * @param context 112 * @param viewId {@link CalendarController.ViewType} 113 */ 114 static void setDefaultView(Context context, int viewId) { 115 SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context); 116 SharedPreferences.Editor editor = prefs.edit(); 117 if (viewId == CalendarController.ViewType.AGENDA 118 || viewId == CalendarController.ViewType.DAY) { 119 // Record the (new) detail start view only for Agenda and Day 120 editor.putInt(CalendarPreferenceActivity.KEY_DETAILED_VIEW, viewId); 121 } 122 123 // Record the (new) start view 124 editor.putInt(CalendarPreferenceActivity.KEY_START_VIEW, viewId); 125 editor.commit(); 126 } 127 128 public static MatrixCursor matrixCursorFromCursor(Cursor cursor) { 129 MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 130 int numColumns = cursor.getColumnCount(); 131 String data[] = new String[numColumns]; 132 cursor.moveToPosition(-1); 133 while (cursor.moveToNext()) { 134 for (int i = 0; i < numColumns; i++) { 135 data[i] = cursor.getString(i); 136 } 137 newCursor.addRow(data); 138 } 139 return newCursor; 140 } 141 142 /** 143 * Compares two cursors to see if they contain the same data. 144 * 145 * @return Returns true of the cursors contain the same data and are not null, false 146 * otherwise 147 */ 148 public static boolean compareCursors(Cursor c1, Cursor c2) { 149 if(c1 == null || c2 == null) { 150 return false; 151 } 152 153 int numColumns = c1.getColumnCount(); 154 if (numColumns != c2.getColumnCount()) { 155 return false; 156 } 157 158 if (c1.getCount() != c2.getCount()) { 159 return false; 160 } 161 162 c1.moveToPosition(-1); 163 c2.moveToPosition(-1); 164 while(c1.moveToNext() && c2.moveToNext()) { 165 for(int i = 0; i < numColumns; i++) { 166 if(!TextUtils.equals(c1.getString(i), c2.getString(i))) { 167 return false; 168 } 169 } 170 } 171 172 return true; 173 } 174 175 /** 176 * If the given intent specifies a time (in milliseconds since the epoch), 177 * then that time is returned. Otherwise, the current time is returned. 178 */ 179 public static final long timeFromIntentInMillis(Intent intent) { 180 // If the time was specified, then use that. Otherwise, use the current time. 181 Uri data = intent.getData(); 182 long millis = intent.getLongExtra(EVENT_BEGIN_TIME, -1); 183 if (millis == -1 && data != null && data.isHierarchical()) { 184 List<String> path = data.getPathSegments(); 185 if(path.size() == 2 && path.get(0).equals("time")) { 186 try { 187 millis = Long.valueOf(data.getLastPathSegment()); 188 } catch (NumberFormatException e) { 189 Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time " + 190 "found. Using current time."); 191 } 192 } 193 } 194 if (millis <= 0) { 195 millis = System.currentTimeMillis(); 196 } 197 return millis; 198 } 199 200 public static Drawable getColorChip(int color) { 201 /* 202 * We want the color chip to have a nice gradient using 203 * the color of the calendar. To do this we use a GradientDrawable. 204 * The color supplied has an alpha of FF so we first do: 205 * color & 0x00FFFFFF 206 * to clear the alpha. Then we add our alpha to it. 207 * We use 3 colors to get a step effect where it starts off very 208 * light and quickly becomes dark and then a slow transition to 209 * be even darker. 210 */ 211 color &= CLEAR_ALPHA_MASK; 212 int startColor = color | HIGH_ALPHA; 213 int middleColor = color | MED_ALPHA; 214 int endColor = color | LOW_ALPHA; 215 int[] colors = new int[] {startColor, middleColor, endColor}; 216 GradientDrawable d = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors); 217 d.setCornerRadii(CORNERS); 218 return d; 219 } 220 221 /** 222 * Formats the given Time object so that it gives the month and year 223 * (for example, "September 2007"). 224 * 225 * @param time the time to format 226 * @return the string containing the weekday and the date 227 */ 228 public static String formatMonthYear(Context context, Time time) { 229 return time.format(context.getResources().getString(R.string.month_year)); 230 } 231 232 /** 233 * Returns a list joined together by the provided delimiter, for example, 234 * ["a", "b", "c"] could be joined into "a,b,c" 235 * 236 * @param things the things to join together 237 * @param delim the delimiter to use 238 * @return a string contained the things joined together 239 */ 240 public static String join(List<?> things, String delim) { 241 StringBuilder builder = new StringBuilder(); 242 boolean first = true; 243 for (Object thing : things) { 244 if (first) { 245 first = false; 246 } else { 247 builder.append(delim); 248 } 249 builder.append(thing.toString()); 250 } 251 return builder.toString(); 252 } 253 254 /** 255 * Get first day of week as android.text.format.Time constant. 256 * @return the first day of week in android.text.format.Time 257 */ 258 public static int getFirstDayOfWeek(Context context) { 259 SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(context); 260 String pref = prefs.getString(CalendarPreferenceActivity.KEY_WEEK_START_DAY, 261 CalendarPreferenceActivity.WEEK_START_DEFAULT); 262 263 int startDay; 264 if (CalendarPreferenceActivity.WEEK_START_DEFAULT.equals(pref)) { 265 startDay = Calendar.getInstance().getFirstDayOfWeek(); 266 } else { 267 startDay = Integer.parseInt(pref); 268 } 269 270 if (startDay == Calendar.SATURDAY) { 271 return Time.SATURDAY; 272 } else if (startDay == Calendar.MONDAY) { 273 return Time.MONDAY; 274 } else { 275 return Time.SUNDAY; 276 } 277 } 278 279 /** 280 * Determine whether the column position is Saturday or not. 281 * @param column the column position 282 * @param firstDayOfWeek the first day of week in android.text.format.Time 283 * @return true if the column is Saturday position 284 */ 285 public static boolean isSaturday(int column, int firstDayOfWeek) { 286 return (firstDayOfWeek == Time.SUNDAY && column == 6) 287 || (firstDayOfWeek == Time.MONDAY && column == 5) 288 || (firstDayOfWeek == Time.SATURDAY && column == 0); 289 } 290 291 /** 292 * Determine whether the column position is Sunday or not. 293 * @param column the column position 294 * @param firstDayOfWeek the first day of week in android.text.format.Time 295 * @return true if the column is Sunday position 296 */ 297 public static boolean isSunday(int column, int firstDayOfWeek) { 298 return (firstDayOfWeek == Time.SUNDAY && column == 0) 299 || (firstDayOfWeek == Time.MONDAY && column == 6) 300 || (firstDayOfWeek == Time.SATURDAY && column == 1); 301 } 302 303 /** 304 * Scan through a cursor of calendars and check if names are duplicated. 305 * 306 * This travels a cursor containing calendar display names and fills in the provided map with 307 * whether or not each name is repeated. 308 * @param isDuplicateName The map to put the duplicate check results in. 309 * @param cursor The query of calendars to check 310 * @param nameIndex The column of the query that contains the display name 311 */ 312 public static void checkForDuplicateNames(Map<String, Boolean> isDuplicateName, Cursor cursor, 313 int nameIndex) { 314 isDuplicateName.clear(); 315 cursor.moveToPosition(-1); 316 while (cursor.moveToNext()) { 317 String displayName = cursor.getString(nameIndex); 318 // Set it to true if we've seen this name before, false otherwise 319 if (displayName != null) { 320 isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName)); 321 } 322 } 323 } 324 325 /** 326 * Null-safe object comparison 327 * @param s1 328 * @param s2 329 * @return 330 */ 331 public static boolean equals(Object o1, Object o2) { 332 return o1 == null ? o2 == null : o1.equals(o2); 333 } 334} 335