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