Utils.java revision 71b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394c
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; 275b2a907fa3a983f74bb48da86846e351c2a464d0Isaac Katzenelsonimport android.content.res.Configuration; 28ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.database.Cursor; 29a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErikimport android.database.MatrixCursor; 301ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.net.Uri; 31d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport android.os.Bundle; 32eb10fa8bee049e0052b5cb53dcfbdaccef9f2740Erikimport android.text.TextUtils; 3329190975b9238dd6841f822f82f2fb83b0557f36Daisuke Miyakawaimport android.text.format.DateUtils; 34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time; 35a48b9d426236d8d26bd99602bf0a84315b3f1b09Erikimport android.util.CalendarUtils.TimeZoneUtils; 361ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.util.Log; 37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelsonimport java.util.ArrayList; 3972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelsonimport java.util.Arrays; 4056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashiimport java.util.Calendar; 411427657d0bf7e69b831aa495828f67b45b69fd99Erikimport java.util.Formatter; 4282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelsonimport java.util.Iterator; 431ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport java.util.List; 44ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport java.util.Map; 4556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi 46146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class Utils { 473dc5e908a825b879978ba523d9099dc2255da9a5Erik private static final boolean DEBUG = true; 483dc5e908a825b879978ba523d9099dc2255da9a5Erik private static final String TAG = "CalUtils"; 49bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan // Set to 0 until we have UI to perform undo 50bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public static final long UNDO_DELAY = 0; 51bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 5279f228124de7d98146ca526d743436f6419e2365Erik // For recurring events which instances of the series are being modified 5379f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_UNINITIALIZED = 0; 5479f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_SELECTED = 1; 5579f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_ALL_FOLLOWING = 2; 5679f228124de7d98146ca526d743436f6419e2365Erik public static final int MODIFY_ALL = 3; 5779f228124de7d98146ca526d743436f6419e2365Erik 587b92da258a480284dcc15a518ea570072329a31dErik // When the edit event view finishes it passes back the appropriate exit 597b92da258a480284dcc15a518ea570072329a31dErik // code. 607b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_REVERT = 1 << 0; 617b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_SAVE = 1 << 1; 627b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_DELETE = 1 << 2; 637b92da258a480284dcc15a518ea570072329a31dErik // And should re run with DONE_EXIT if it should also leave the view, just 647b92da258a480284dcc15a518ea570072329a31dErik // exiting is identical to reverting 657b92da258a480284dcc15a518ea570072329a31dErik public static final int DONE_EXIT = 1 << 0; 6679f228124de7d98146ca526d743436f6419e2365Erik 67ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan protected static final String OPEN_EMAIL_MARKER = " <"; 68ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan protected static final String CLOSE_EMAIL_MARKER = ">"; 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"; 73275232dae58bb24e3360a779ada9d24601a99bcfErik 74981874e61ecf29a96a77601a3172b2503b6537eeErik public static final int MONDAY_BEFORE_JULIAN_EPOCH = Time.EPOCH_JULIAN_DAY - 3; 75981874e61ecf29a96a77601a3172b2503b6537eeErik 76a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // The name of the shared preferences file. This name must be maintained for 77a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // historical 78a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // reasons, as it's what PreferenceManager assigned the first time the file 79a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik // was created. 80a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik private static final String SHARED_PREFS_NAME = "com.android.calendar_preferences"; 8135d1362a75eac7cebbe9de23d08fea08c4aac817Erik 82a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik private static final TimeZoneUtils mTZUtils = new TimeZoneUtils(SHARED_PREFS_NAME); 83b60218a31d948ea0a549daf6464063d20b48421fMichael Chan private static boolean mAllowWeekForDetailView = false; 84ca4786769151f97069980443ce43d9c4f867ac5bErik private static long mTardis = 0; 85d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 86d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static int getViewTypeFromIntentAndSharedPref(Activity activity) { 87dd95df57c8c5a58a85c4c0effad5652dec14f621Erik Intent intent = activity.getIntent(); 88dd95df57c8c5a58a85c4c0effad5652dec14f621Erik Bundle extras = intent.getExtras(); 894b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(activity); 90d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 917b92da258a480284dcc15a518ea570072329a31dErik if (TextUtils.equals(intent.getAction(), Intent.ACTION_EDIT)) { 92dd95df57c8c5a58a85c4c0effad5652dec14f621Erik return ViewType.EDIT; 93dd95df57c8c5a58a85c4c0effad5652dec14f621Erik } 94d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan if (extras != null) { 95d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan if (extras.getBoolean(INTENT_KEY_DETAIL_VIEW, false)) { 96d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan // This is the "detail" view which is either agenda or day view 974b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa return prefs.getInt(GeneralPreferences.KEY_DETAILED_VIEW, 984b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa GeneralPreferences.DEFAULT_DETAILED_VIEW); 99d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } else if (INTENT_VALUE_VIEW_TYPE_DAY.equals(extras.getString(INTENT_KEY_VIEW_TYPE))) { 100d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan // Not sure who uses this. This logic came from LaunchActivity 101d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan return ViewType.DAY; 102d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 103d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 104d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 105d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan // Default to the last view 1067b92da258a480284dcc15a518ea570072329a31dErik return prefs.getInt( 1077b92da258a480284dcc15a518ea570072329a31dErik GeneralPreferences.KEY_START_VIEW, GeneralPreferences.DEFAULT_START_VIEW); 108d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 109ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan 110235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik /** 1117b92da258a480284dcc15a518ea570072329a31dErik * Writes a new home time zone to the db. Updates the home time zone in the 1127b92da258a480284dcc15a518ea570072329a31dErik * db asynchronously and updates the local cache. Sending a time zone of 1137b92da258a480284dcc15a518ea570072329a31dErik * **tbd** will cause it to be set to the device's time zone. null or empty 1147b92da258a480284dcc15a518ea570072329a31dErik * tz will be ignored. 1153dc5e908a825b879978ba523d9099dc2255da9a5Erik * 1163dc5e908a825b879978ba523d9099dc2255da9a5Erik * @param context The calling activity 1173dc5e908a825b879978ba523d9099dc2255da9a5Erik * @param timeZone The time zone to set Calendar to, or **tbd** 1183dc5e908a825b879978ba523d9099dc2255da9a5Erik */ 1193dc5e908a825b879978ba523d9099dc2255da9a5Erik public static void setTimeZone(Context context, String timeZone) { 120a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik mTZUtils.setTimeZone(context, timeZone); 1213dc5e908a825b879978ba523d9099dc2255da9a5Erik } 1223dc5e908a825b879978ba523d9099dc2255da9a5Erik 1233dc5e908a825b879978ba523d9099dc2255da9a5Erik /** 1247b92da258a480284dcc15a518ea570072329a31dErik * Gets the time zone that Calendar should be displayed in This is a helper 1257b92da258a480284dcc15a518ea570072329a31dErik * method to get the appropriate time zone for Calendar. If this is the 1267b92da258a480284dcc15a518ea570072329a31dErik * first time this method has been called it will initiate an asynchronous 1277b92da258a480284dcc15a518ea570072329a31dErik * query to verify that the data in preferences is correct. The callback 1287b92da258a480284dcc15a518ea570072329a31dErik * supplied will only be called if this query returns a value other than 1297b92da258a480284dcc15a518ea570072329a31dErik * what is stored in preferences and should cause the calling activity to 1307b92da258a480284dcc15a518ea570072329a31dErik * refresh anything that depends on calling this method. 131235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik * 132235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik * @param context The calling activity 1337b92da258a480284dcc15a518ea570072329a31dErik * @param callback The runnable that should execute if a query returns new 1347b92da258a480284dcc15a518ea570072329a31dErik * values 1357b92da258a480284dcc15a518ea570072329a31dErik * @return The string value representing the time zone Calendar should 1367b92da258a480284dcc15a518ea570072329a31dErik * display 137235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik */ 138235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik public static String getTimeZone(Context context, Runnable callback) { 139a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik return mTZUtils.getTimeZone(context, callback); 14045efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan } 14145efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan 1421427657d0bf7e69b831aa495828f67b45b69fd99Erik /** 1431427657d0bf7e69b831aa495828f67b45b69fd99Erik * Formats a date or a time range according to the local conventions. 1441427657d0bf7e69b831aa495828f67b45b69fd99Erik * 1451427657d0bf7e69b831aa495828f67b45b69fd99Erik * @param context the context is required only if the time is shown 1461427657d0bf7e69b831aa495828f67b45b69fd99Erik * @param startMillis the start time in UTC milliseconds 1471427657d0bf7e69b831aa495828f67b45b69fd99Erik * @param endMillis the end time in UTC milliseconds 14829190975b9238dd6841f822f82f2fb83b0557f36Daisuke Miyakawa * @param flags a bit mask of options See {@link DateUtils#formatDateRange(Context, Formatter, 14929190975b9238dd6841f822f82f2fb83b0557f36Daisuke Miyakawa * long, long, int, String) formatDateRange} 1501427657d0bf7e69b831aa495828f67b45b69fd99Erik * @return a string containing the formatted date/time range. 1511427657d0bf7e69b831aa495828f67b45b69fd99Erik */ 1527b92da258a480284dcc15a518ea570072329a31dErik public static String formatDateRange( 1537b92da258a480284dcc15a518ea570072329a31dErik Context context, long startMillis, long endMillis, int flags) { 154a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik return mTZUtils.formatDateRange(context, startMillis, endMillis, flags); 155a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik } 156a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik 157a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik public static String getSharedPreference(Context context, String key, String defaultValue) { 158a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 159a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik return prefs.getString(key, defaultValue); 1601427657d0bf7e69b831aa495828f67b45b69fd99Erik } 1611427657d0bf7e69b831aa495828f67b45b69fd99Erik 162d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan public static int getSharedPreference(Context context, String key, int defaultValue) { 1634b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 164d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan return prefs.getInt(key, defaultValue); 165d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } 166d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan 167ca4786769151f97069980443ce43d9c4f867ac5bErik public static boolean getSharedPreference(Context context, String key, boolean defaultValue) { 168ca4786769151f97069980443ce43d9c4f867ac5bErik SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 169ca4786769151f97069980443ce43d9c4f867ac5bErik return prefs.getBoolean(key, defaultValue); 170ca4786769151f97069980443ce43d9c4f867ac5bErik } 171ca4786769151f97069980443ce43d9c4f867ac5bErik 172f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang /** 173f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * Asynchronously sets the preference with the given key to the given value 174f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * 175f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * @param context the context to use to get preferences from 176f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * @param key the key of the preference to set 177f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang * @param value the value to set 178f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang */ 179fbce65e53c7a111955f638db5bf8bee35381e5b7Erik public static void setSharedPreference(Context context, String key, String value) { 1804b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 18124fac46d6b87ce21d5e6a4b1c0fdcaa83d408997Brad Fitzpatrick prefs.edit().putString(key, value).apply(); 18245efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan } 18345efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan 184ca4786769151f97069980443ce43d9c4f867ac5bErik protected static void tardis() { 185ca4786769151f97069980443ce43d9c4f867ac5bErik mTardis = System.currentTimeMillis(); 186ca4786769151f97069980443ce43d9c4f867ac5bErik } 187ca4786769151f97069980443ce43d9c4f867ac5bErik 188ca4786769151f97069980443ce43d9c4f867ac5bErik protected static long getTardis() { 189ca4786769151f97069980443ce43d9c4f867ac5bErik return mTardis; 190ca4786769151f97069980443ce43d9c4f867ac5bErik } 191ca4786769151f97069980443ce43d9c4f867ac5bErik 1923dc5e908a825b879978ba523d9099dc2255da9a5Erik static void setSharedPreference(Context context, String key, boolean value) { 1934b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 1943dc5e908a825b879978ba523d9099dc2255da9a5Erik SharedPreferences.Editor editor = prefs.edit(); 1953dc5e908a825b879978ba523d9099dc2255da9a5Erik editor.putBoolean(key, value); 196275232dae58bb24e3360a779ada9d24601a99bcfErik editor.apply(); 1973dc5e908a825b879978ba523d9099dc2255da9a5Erik } 1983dc5e908a825b879978ba523d9099dc2255da9a5Erik 199d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan static void setSharedPreference(Context context, String key, int value) { 200d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 201d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan SharedPreferences.Editor editor = prefs.edit(); 202d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan editor.putInt(key, value); 203d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan editor.apply(); 204d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 205d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 206d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan /** 207d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * Save default agenda/day/week/month view for next time 208d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * 209d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * @param context 210d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * @param viewId {@link CalendarController.ViewType} 211d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan */ 212e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan static void setDefaultView(Context context, int viewId) { 2134b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 214e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan SharedPreferences.Editor editor = prefs.edit(); 215f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang 216b60218a31d948ea0a549daf6464063d20b48421fMichael Chan boolean validDetailView = false; 217b60218a31d948ea0a549daf6464063d20b48421fMichael Chan if (mAllowWeekForDetailView && viewId == CalendarController.ViewType.WEEK) { 218b60218a31d948ea0a549daf6464063d20b48421fMichael Chan validDetailView = true; 219b60218a31d948ea0a549daf6464063d20b48421fMichael Chan } else { 220b60218a31d948ea0a549daf6464063d20b48421fMichael Chan validDetailView = viewId == CalendarController.ViewType.AGENDA 221b60218a31d948ea0a549daf6464063d20b48421fMichael Chan || viewId == CalendarController.ViewType.DAY; 222b60218a31d948ea0a549daf6464063d20b48421fMichael Chan } 223b60218a31d948ea0a549daf6464063d20b48421fMichael Chan 224b60218a31d948ea0a549daf6464063d20b48421fMichael Chan if (validDetailView) { 225b60218a31d948ea0a549daf6464063d20b48421fMichael Chan // Record the detail start view 2264b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa editor.putInt(GeneralPreferences.KEY_DETAILED_VIEW, viewId); 227e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan } 228e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan 229e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan // Record the (new) start view 2304b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa editor.putInt(GeneralPreferences.KEY_START_VIEW, viewId); 23124fac46d6b87ce21d5e6a4b1c0fdcaa83d408997Brad Fitzpatrick editor.apply(); 232e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan } 233e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan 234a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik public static MatrixCursor matrixCursorFromCursor(Cursor cursor) { 235a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 236a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik int numColumns = cursor.getColumnCount(); 237a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik String data[] = new String[numColumns]; 238a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik cursor.moveToPosition(-1); 239a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik while (cursor.moveToNext()) { 240a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik for (int i = 0; i < numColumns; i++) { 241a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik data[i] = cursor.getString(i); 242a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 243a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik newCursor.addRow(data); 244a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 245a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return newCursor; 246a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 247a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 248a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik /** 249a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik * Compares two cursors to see if they contain the same data. 250a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik * 2517b92da258a480284dcc15a518ea570072329a31dErik * @return Returns true of the cursors contain the same data and are not 2527b92da258a480284dcc15a518ea570072329a31dErik * null, false otherwise 253a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik */ 254a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik public static boolean compareCursors(Cursor c1, Cursor c2) { 2557b92da258a480284dcc15a518ea570072329a31dErik if (c1 == null || c2 == null) { 256a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 257a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 258a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 259a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik int numColumns = c1.getColumnCount(); 260a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik if (numColumns != c2.getColumnCount()) { 261a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 262a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 263a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 264a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik if (c1.getCount() != c2.getCount()) { 265a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 266a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 267a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 268a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik c1.moveToPosition(-1); 269a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik c2.moveToPosition(-1); 2707b92da258a480284dcc15a518ea570072329a31dErik while (c1.moveToNext() && c2.moveToNext()) { 2717b92da258a480284dcc15a518ea570072329a31dErik for (int i = 0; i < numColumns; i++) { 2727b92da258a480284dcc15a518ea570072329a31dErik if (!TextUtils.equals(c1.getString(i), c2.getString(i))) { 273a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return false; 274a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 275a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 276a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 277a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 278a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik return true; 279a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik } 280a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik 281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * If the given intent specifies a time (in milliseconds since the epoch), 283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * then that time is returned. Otherwise, the current time is returned. 284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public static final long timeFromIntentInMillis(Intent intent) { 2867b92da258a480284dcc15a518ea570072329a31dErik // If the time was specified, then use that. Otherwise, use the current 2877b92da258a480284dcc15a518ea570072329a31dErik // time. 2881ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik Uri data = intent.getData(); 289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = intent.getLongExtra(EVENT_BEGIN_TIME, -1); 2901ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik if (millis == -1 && data != null && data.isHierarchical()) { 2911ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik List<String> path = data.getPathSegments(); 2927b92da258a480284dcc15a518ea570072329a31dErik if (path.size() == 2 && path.get(0).equals("time")) { 2931ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik try { 2941ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik millis = Long.valueOf(data.getLastPathSegment()); 2951ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } catch (NumberFormatException e) { 2967b92da258a480284dcc15a518ea570072329a31dErik Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time " 2977b92da258a480284dcc15a518ea570072329a31dErik + "found. Using current time."); 2981ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } 2991ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } 3001ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik } 30176727b7a9cf780f200414548b9d454bf9a701e3eErik if (millis <= 0) { 302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project millis = System.currentTimeMillis(); 303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return millis; 305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3087b92da258a480284dcc15a518ea570072329a31dErik * Formats the given Time object so that it gives the month and year (for 3097b92da258a480284dcc15a518ea570072329a31dErik * example, "September 2007"). 310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param time the time to format 312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return the string containing the weekday and the date 313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 314ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan public static String formatMonthYear(Context context, Time time) { 315cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY 316cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik | DateUtils.FORMAT_SHOW_YEAR; 317cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik long millis = time.toMillis(true); 318cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik return formatDateRange(context, millis, millis, flags); 319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3224c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * Returns a list joined together by the provided delimiter, for example, 3234c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * ["a", "b", "c"] could be joined into "a,b,c" 3244c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * 3254c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * @param things the things to join together 3264c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * @param delim the delimiter to use 3274c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang * @return a string contained the things joined together 3284c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang */ 3294c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang public static String join(List<?> things, String delim) { 3304c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang StringBuilder builder = new StringBuilder(); 3314c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang boolean first = true; 3324c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang for (Object thing : things) { 3334c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang if (first) { 3344c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang first = false; 3354c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } else { 3364c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang builder.append(delim); 3374c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } 3384c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang builder.append(thing.toString()); 3394c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } 3404c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang return builder.toString(); 3414c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang } 3424c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang 3434c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang /** 344981874e61ecf29a96a77601a3172b2503b6537eeErik * Returns the week since {@link Time#EPOCH_JULIAN_DAY} (Jan 1, 1970) 345981874e61ecf29a96a77601a3172b2503b6537eeErik * adjusted for first day of week. 346981874e61ecf29a96a77601a3172b2503b6537eeErik * 347981874e61ecf29a96a77601a3172b2503b6537eeErik * This takes a julian day and the week start day and calculates which 348981874e61ecf29a96a77601a3172b2503b6537eeErik * week since {@link Time#EPOCH_JULIAN_DAY} that day occurs in, starting 349981874e61ecf29a96a77601a3172b2503b6537eeErik * at 0. *Do not* use this to compute the ISO week number for the year. 350981874e61ecf29a96a77601a3172b2503b6537eeErik * 351981874e61ecf29a96a77601a3172b2503b6537eeErik * @param julianDay The julian day to calculate the week number for 352981874e61ecf29a96a77601a3172b2503b6537eeErik * @param firstDayOfWeek Which week day is the first day of the week, 353981874e61ecf29a96a77601a3172b2503b6537eeErik * see {@link Time#SUNDAY} 354981874e61ecf29a96a77601a3172b2503b6537eeErik * @return Weeks since the epoch 355981874e61ecf29a96a77601a3172b2503b6537eeErik */ 356981874e61ecf29a96a77601a3172b2503b6537eeErik public static int getWeeksSinceEpochFromJulianDay(int julianDay, int firstDayOfWeek) { 357981874e61ecf29a96a77601a3172b2503b6537eeErik int diff = Time.THURSDAY - firstDayOfWeek; 358981874e61ecf29a96a77601a3172b2503b6537eeErik if (diff < 0) { 359981874e61ecf29a96a77601a3172b2503b6537eeErik diff += 7; 360981874e61ecf29a96a77601a3172b2503b6537eeErik } 361981874e61ecf29a96a77601a3172b2503b6537eeErik int refDay = Time.EPOCH_JULIAN_DAY - diff; 362981874e61ecf29a96a77601a3172b2503b6537eeErik return (julianDay - refDay) / 7; 363981874e61ecf29a96a77601a3172b2503b6537eeErik } 364981874e61ecf29a96a77601a3172b2503b6537eeErik 365981874e61ecf29a96a77601a3172b2503b6537eeErik /** 366981874e61ecf29a96a77601a3172b2503b6537eeErik * Takes a number of weeks since the epoch and calculates the Julian day of 367981874e61ecf29a96a77601a3172b2503b6537eeErik * the Monday for that week. 368981874e61ecf29a96a77601a3172b2503b6537eeErik * 369981874e61ecf29a96a77601a3172b2503b6537eeErik * This assumes that the week containing the {@link Time#EPOCH_JULIAN_DAY} 370981874e61ecf29a96a77601a3172b2503b6537eeErik * is considered week 0. It returns the Julian day for the Monday 371981874e61ecf29a96a77601a3172b2503b6537eeErik * {@code week} weeks after the Monday of the week containing the epoch. 372981874e61ecf29a96a77601a3172b2503b6537eeErik * 373981874e61ecf29a96a77601a3172b2503b6537eeErik * @param week Number of weeks since the epoch 374981874e61ecf29a96a77601a3172b2503b6537eeErik * @return The julian day for the Monday of the given week since the epoch 375981874e61ecf29a96a77601a3172b2503b6537eeErik */ 376981874e61ecf29a96a77601a3172b2503b6537eeErik public static int getJulianMondayFromWeeksSinceEpoch(int week) { 377981874e61ecf29a96a77601a3172b2503b6537eeErik return MONDAY_BEFORE_JULIAN_EPOCH + week * 7; 378981874e61ecf29a96a77601a3172b2503b6537eeErik } 379981874e61ecf29a96a77601a3172b2503b6537eeErik 380981874e61ecf29a96a77601a3172b2503b6537eeErik /** 38156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * Get first day of week as android.text.format.Time constant. 3827b92da258a480284dcc15a518ea570072329a31dErik * 38356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @return the first day of week in android.text.format.Time 38456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi */ 3858e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang public static int getFirstDayOfWeek(Context context) { 3864b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 3877b92da258a480284dcc15a518ea570072329a31dErik String pref = prefs.getString( 3887b92da258a480284dcc15a518ea570072329a31dErik GeneralPreferences.KEY_WEEK_START_DAY, GeneralPreferences.WEEK_START_DEFAULT); 3898e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang 3908e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang int startDay; 3914b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa if (GeneralPreferences.WEEK_START_DEFAULT.equals(pref)) { 3928e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang startDay = Calendar.getInstance().getFirstDayOfWeek(); 3938e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang } else { 3948e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang startDay = Integer.parseInt(pref); 3958e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang } 3968e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang 39756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi if (startDay == Calendar.SATURDAY) { 39856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return Time.SATURDAY; 39956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } else if (startDay == Calendar.MONDAY) { 40056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return Time.MONDAY; 40156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } else { 40256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return Time.SUNDAY; 40356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 40456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 40556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi 40656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi /** 407d644b0df14ae6e204369b3454d16976fba32f15cDaisuke Miyakawa * @return true when week number should be shown. 408981874e61ecf29a96a77601a3172b2503b6537eeErik */ 409981874e61ecf29a96a77601a3172b2503b6537eeErik public static boolean getShowWeekNumber(Context context) { 410d644b0df14ae6e204369b3454d16976fba32f15cDaisuke Miyakawa final SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 411981874e61ecf29a96a77601a3172b2503b6537eeErik return prefs.getBoolean( 412981874e61ecf29a96a77601a3172b2503b6537eeErik GeneralPreferences.KEY_SHOW_WEEK_NUM, GeneralPreferences.DEFAULT_SHOW_WEEK_NUM); 413981874e61ecf29a96a77601a3172b2503b6537eeErik } 414981874e61ecf29a96a77601a3172b2503b6537eeErik 415981874e61ecf29a96a77601a3172b2503b6537eeErik /** 41640bcd101b212c9863c3110c05a487a7ae6ebc3caErik * @return true when declined events should be hidden. 41740bcd101b212c9863c3110c05a487a7ae6ebc3caErik */ 41840bcd101b212c9863c3110c05a487a7ae6ebc3caErik public static boolean getHideDeclinedEvents(Context context) { 41940bcd101b212c9863c3110c05a487a7ae6ebc3caErik final SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 42040bcd101b212c9863c3110c05a487a7ae6ebc3caErik return prefs.getBoolean(GeneralPreferences.KEY_HIDE_DECLINED, false); 42140bcd101b212c9863c3110c05a487a7ae6ebc3caErik } 42240bcd101b212c9863c3110c05a487a7ae6ebc3caErik 42391b01ed605e36fc5a7a924c226597a62c789b50dErik public static int getDaysPerWeek(Context context) { 42491b01ed605e36fc5a7a924c226597a62c789b50dErik final SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 42591b01ed605e36fc5a7a924c226597a62c789b50dErik return prefs.getInt(GeneralPreferences.KEY_DAYS_PER_WEEK, 7); 42691b01ed605e36fc5a7a924c226597a62c789b50dErik } 42791b01ed605e36fc5a7a924c226597a62c789b50dErik 42840bcd101b212c9863c3110c05a487a7ae6ebc3caErik /** 42956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * Determine whether the column position is Saturday or not. 4307b92da258a480284dcc15a518ea570072329a31dErik * 43156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param column the column position 43256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param firstDayOfWeek the first day of week in android.text.format.Time 43356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @return true if the column is Saturday position 43456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi */ 43556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi public static boolean isSaturday(int column, int firstDayOfWeek) { 43656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return (firstDayOfWeek == Time.SUNDAY && column == 6) 4377b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.MONDAY && column == 5) 4387b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.SATURDAY && column == 0); 43956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 44056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi 44156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi /** 44256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * Determine whether the column position is Sunday or not. 4437b92da258a480284dcc15a518ea570072329a31dErik * 44456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param column the column position 44556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @param firstDayOfWeek the first day of week in android.text.format.Time 44656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi * @return true if the column is Sunday position 44756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi */ 44856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi public static boolean isSunday(int column, int firstDayOfWeek) { 44956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi return (firstDayOfWeek == Time.SUNDAY && column == 0) 4507b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.MONDAY && column == 6) 4517b92da258a480284dcc15a518ea570072329a31dErik || (firstDayOfWeek == Time.SATURDAY && column == 1); 45256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi } 453ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan 454ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan /** 4559da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik * Convert given UTC time into current local time. This assumes it is for an 4569da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik * allday event and will adjust the time to be on a midnight boundary. 4573ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang * 4583ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang * @param recycle Time object to recycle, otherwise null. 4593ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang * @param utcTime Time to convert, in UTC. 4609da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik * @param tz The time zone to convert this time to. 4613ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang */ 4629da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik public static long convertAlldayUtcToLocal(Time recycle, long utcTime, String tz) { 4633ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang if (recycle == null) { 4643ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang recycle = new Time(); 4653ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang } 4663ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang recycle.timezone = Time.TIMEZONE_UTC; 4673ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang recycle.set(utcTime); 4689da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik recycle.timezone = tz; 4699da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik return recycle.normalize(true); 4709da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik } 4719da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik 4729da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik public static long convertAlldayLocalToUTC(Time recycle, long localTime, String tz) { 4739da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik if (recycle == null) { 4749da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik recycle = new Time(); 4759da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik } 4769da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik recycle.timezone = tz; 4779da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik recycle.set(localTime); 4789da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik recycle.timezone = Time.TIMEZONE_UTC; 4793ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang return recycle.normalize(true); 4803ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang } 4813ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang 4823ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang /** 483ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * Scan through a cursor of calendars and check if names are duplicated. 4847b92da258a480284dcc15a518ea570072329a31dErik * This travels a cursor containing calendar display names and fills in the 4857b92da258a480284dcc15a518ea570072329a31dErik * provided map with whether or not each name is repeated. 486ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * 487ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * @param isDuplicateName The map to put the duplicate check results in. 488ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * @param cursor The query of calendars to check 489ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan * @param nameIndex The column of the query that contains the display name 490ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan */ 4917b92da258a480284dcc15a518ea570072329a31dErik public static void checkForDuplicateNames( 4927b92da258a480284dcc15a518ea570072329a31dErik Map<String, Boolean> isDuplicateName, Cursor cursor, int nameIndex) { 493ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan isDuplicateName.clear(); 494ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan cursor.moveToPosition(-1); 495ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan while (cursor.moveToNext()) { 496ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan String displayName = cursor.getString(nameIndex); 497ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan // Set it to true if we've seen this name before, false otherwise 498ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan if (displayName != null) { 499ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName)); 500ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan } 501ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan } 502ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan } 5039138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang 5049138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** 5059138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * Null-safe object comparison 5067b92da258a480284dcc15a518ea570072329a31dErik * 5079138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * @param s1 5089138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * @param s2 5099138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang * @return 5109138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang */ 5119138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang public static boolean equals(Object o1, Object o2) { 5129138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang return o1 == null ? o2 == null : o1.equals(o2); 5139138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang } 514b60218a31d948ea0a549daf6464063d20b48421fMichael Chan 51563cd053150e00fde045b019dbe0f48b8a9ed3559Erik public static void setAllowWeekForDetailView(boolean allowWeekView) { 516b60218a31d948ea0a549daf6464063d20b48421fMichael Chan mAllowWeekForDetailView = allowWeekView; 517b60218a31d948ea0a549daf6464063d20b48421fMichael Chan } 51863cd053150e00fde045b019dbe0f48b8a9ed3559Erik 51963cd053150e00fde045b019dbe0f48b8a9ed3559Erik public static boolean getAllowWeekForDetailView() { 52063cd053150e00fde045b019dbe0f48b8a9ed3559Erik return mAllowWeekForDetailView; 52163cd053150e00fde045b019dbe0f48b8a9ed3559Erik } 5220b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson 5230b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson public static boolean isMultiPaneConfiguration (Context c) { 5240b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson return (c.getResources().getConfiguration().screenLayout & 5250b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson Configuration.SCREENLAYOUT_SIZE_XLARGE) != 0; 5260b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson } 527ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson 528ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson public static boolean getConfigBool(Context c, int key) { 529ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson return c.getResources().getBoolean(key); 530ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson } 53182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 53282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 53371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson /** 53472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * This is a helper class for the createBusyBitSegments method 53572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * The class contains information about a specific time that corresponds to either a start 53672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * of an event or an end of an event (or both): 53772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * 1. The time itself 53872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * 2 .The number of event starts and ends (number of starts - number of ends) 53972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson */ 54082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 54172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson private static class BusyBitsEventTime { 54282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 54372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson public static final int EVENT_START = 1; 54472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson public static final int EVENT_END = -1; 545c18dd7aea8c8ee06dd34f268ea9e0e9e7c235b7fIsaac Katzenelson 54672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson public int mTime; // in minutes 54772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Number of events that start and end in this time (+1 for each start, 54872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // -1 for each end) 54972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson public int mStartEndChanges; 55072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 55172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson public BusyBitsEventTime(int t, int c) { 55272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson mTime = t; 55372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson mStartEndChanges = c; 554c18dd7aea8c8ee06dd34f268ea9e0e9e7c235b7fIsaac Katzenelson } 55572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 55672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson public void addStart() { 55772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson mStartEndChanges++; 558c18dd7aea8c8ee06dd34f268ea9e0e9e7c235b7fIsaac Katzenelson } 559c18dd7aea8c8ee06dd34f268ea9e0e9e7c235b7fIsaac Katzenelson 56072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson public void addEnd() { 56172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson mStartEndChanges--; 56272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 56372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 56472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 56572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson /** 56672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * Corrects segments that are overlapping. 56771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * The function makes sure the last segment inserted do not overlap with segments in the 56871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * segments arrays. It will compare the last inserted segment to last segment in both the 56971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * busy array and conflicting array and make corrections to segments if necessary. 57072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * The function assumes an overlap could be only 1 pixel. 57172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * The function removes segments if necessary 57272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * Segment size is from start to end (inclusive) 57372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * 57471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * @param segments segments an array of 2 float arrays. The first array will contain the 57571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * coordinates for drawing busy segments, the second will contain the coordinates for 57671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * drawing conflicting segments. The first cell in each array contains the number of 57771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * used cell so this method can be called again without overriding data, 57871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * @param arrayIndex - index of the segments array that got the last segment 57971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * @param prevSegmentInserted - an indicator of the type of the previous segment inserted. This 58071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * 58171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * @return boolean telling the calling functions whether to add the last segment or not. 58271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * The calling function should first insert a new segment to the array, call this 58371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * function and when getting a "true" value in the return value, update the counter of 58471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * the array to indicate a new segment (Add 4 to the counter in cell 0). 58572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson */ 58672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 58771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson static final int START_PIXEL_Y = 1; // index of pixel locations in a coordinates set 58871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson static final int END_PIXEL_Y = 3; 58971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson static final int BUSY_ARRAY_INDEX = 0; 59071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson static final int CONFLICT_ARRAY_INDEX = 1; 59171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson static final int COUNTER_INDEX = 0; 59272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 59371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson static final int NO_PREV_INSERTED = 0; // possible status of previous segment insertion 59471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson static final int BUSY_PREV_INSERTED = 1; 59571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson static final int CONFLICT_PREV_INSERTED = 2; 59672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 59772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 59871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson public static boolean correctOverlappingSegment(float[][] segments, 59971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int arrayIndex, int prevSegmentInserted) { 60071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 60171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (prevSegmentInserted == NO_PREV_INSERTED) { 60271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // First segment - add it 60371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return true; 60472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 60571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 60671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Previous insert and this one are to the busy array 60771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (prevSegmentInserted == BUSY_PREV_INSERTED && arrayIndex == BUSY_ARRAY_INDEX) { 60871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 60971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Index of last and previously inserted segment 61071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iLast = 1 + (int) segments[BUSY_ARRAY_INDEX][COUNTER_INDEX]; 61171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iPrev = 1 + (int) segments[BUSY_ARRAY_INDEX][COUNTER_INDEX] - 4; 61271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 61371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Segments do not overlap - add the new one 61471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (segments[BUSY_ARRAY_INDEX][iPrev + END_PIXEL_Y] < 61571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[BUSY_ARRAY_INDEX][iLast + START_PIXEL_Y]) { 61671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return true; 61771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } 61871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 61971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Segments overlap - merge them 62071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[BUSY_ARRAY_INDEX][iPrev + END_PIXEL_Y] = 62171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[BUSY_ARRAY_INDEX][iLast + END_PIXEL_Y]; 62271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return false; 62372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 62472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 62571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Previous insert was to the busy array and this one is to the conflict array 62671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (prevSegmentInserted == BUSY_PREV_INSERTED && arrayIndex == CONFLICT_ARRAY_INDEX) { 62771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 62871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Index of last and previously inserted segment 62971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iLast = 1 + (int) segments[CONFLICT_ARRAY_INDEX][COUNTER_INDEX]; 63071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iPrev = 1 + (int) segments[BUSY_ARRAY_INDEX][COUNTER_INDEX] - 4; 63171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 63271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Segments do not overlap - add the new one 63371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (segments[BUSY_ARRAY_INDEX][iPrev + END_PIXEL_Y] < 63471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[CONFLICT_ARRAY_INDEX][iLast + START_PIXEL_Y]) { 63571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return true; 63672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 63771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 63871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Segments overlap - truncate the end of the last busy segment 63971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // if it disappears , remove it 64071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[BUSY_ARRAY_INDEX][iPrev + END_PIXEL_Y]--; 64171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (segments[BUSY_ARRAY_INDEX][iPrev + END_PIXEL_Y] < 64271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[BUSY_ARRAY_INDEX][iPrev + START_PIXEL_Y]) { 64371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[BUSY_ARRAY_INDEX] [COUNTER_INDEX] -= 4; 64472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 64571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return true; 64671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } 64771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Previous insert was to the conflict array and this one is to the busy array 64871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (prevSegmentInserted == CONFLICT_PREV_INSERTED && arrayIndex == BUSY_ARRAY_INDEX) { 64971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 65071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Index of last and previously inserted segment 65171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iLast = 1 + (int) segments[BUSY_ARRAY_INDEX][COUNTER_INDEX]; 65271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iPrev = 1 + (int) segments[CONFLICT_ARRAY_INDEX][COUNTER_INDEX] - 4; 65371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 65471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Segments do not overlap - add the new one 65571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (segments[CONFLICT_ARRAY_INDEX][iPrev + END_PIXEL_Y] < 65671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[BUSY_ARRAY_INDEX][iLast + START_PIXEL_Y]) { 65771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return true; 65872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 65971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 66071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Segments overlap - truncate the new busy segment , if it disappears , do not 66171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // insert it 66271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[BUSY_ARRAY_INDEX][iLast + START_PIXEL_Y]++; 66371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (segments[BUSY_ARRAY_INDEX][iLast + START_PIXEL_Y] > 66471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[BUSY_ARRAY_INDEX][iLast + END_PIXEL_Y]) { 66571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return false; 66671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } 66771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return true; 66871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 66972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 67071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Previous insert and this one are to the conflict array 67171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (prevSegmentInserted == CONFLICT_PREV_INSERTED && arrayIndex == CONFLICT_ARRAY_INDEX) { 67271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 67371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Index of last and previously inserted segment 67471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iLast = 1 + (int) segments[CONFLICT_ARRAY_INDEX][COUNTER_INDEX]; 67571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iPrev = 1 + (int) segments[CONFLICT_ARRAY_INDEX][COUNTER_INDEX] - 4; 67682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 67771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Segments do not overlap - add the new one 67871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (segments[CONFLICT_ARRAY_INDEX][iPrev + END_PIXEL_Y] < 67971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[CONFLICT_ARRAY_INDEX][iLast + START_PIXEL_Y]) { 68071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return true; 68171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } 68271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 68371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Segments overlap - merge them 68471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[CONFLICT_ARRAY_INDEX][iPrev + END_PIXEL_Y] = 68571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments[CONFLICT_ARRAY_INDEX][iLast + END_PIXEL_Y]; 68671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return false; 68771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } 68871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Unknown state , complain 68971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson Log.wtf(TAG, "Unkown state in correctOverlappingSegment: prevSegmentInserted = " + 69071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson prevSegmentInserted + " arrayIndex = " + arrayIndex); 69171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return false; 69271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } 69372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 69472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson /** 69572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * Converts a list of events to a list of busy segments to draw. 69672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * Assumes list is ordered according to start time of events 69772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * The function processes events of a specific day only or part of that day 69872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * 69972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * The algorithm goes over all the events and creates an ordered list of times. 70072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * Each item on the list corresponds to a time where an event started,ended or both. 70172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * The item has a count of how many events started and how many events ended at that time. 70272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * In the second stage, the algorithm go over the list of times and finds what change happened 70371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * at each time. A change can be a switch between either of the free time/busy time/conflicting 70472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * time. Every time a change happens, the algorithm creates a segment (in pixels) to be 70571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * displayed with the relevant status (free/busy/conflicting). 70672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * The algorithm also checks if segments overlap and truncates one of them if needed. 70772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * 70872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * @param startPixel defines the start of the draw area 70972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * @param endPixel defines the end of the draw area 71071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * @param xPixel the middle X position of the draw area 71172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * @param startTimeMinute start time (in minutes) of the time frame to be displayed as busy bits 71272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * @param endTimeMinute end time (in minutes) of the time frame to be displayed as busy bits 71372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * @param julianDay the day of the time frame 71472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * @param daysEvents - a list of events that took place in the specified day (including 71572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * recurring events, events that start before the day and/or end after 71672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson * the day 71771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * @param segments an array of 2 float arrays. The first array will contain the coordinates 71871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * for drawing busy segments, the second will contain the coordinates for drawing 71971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * conflicting segments. The first cell in each array contains the number of used cell 72071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * so this method can be called again without overriding data, 72171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson * 72272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson */ 72372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 72471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson public static void createBusyBitSegments(int startPixel, int endPixel, 72571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int xPixel, int startTimeMinute, int endTimeMinute, int julianDay, 72671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson ArrayList<Event> daysEvents, float [] [] segments) { 72772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 72872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // No events or illegal parameters , do nothing 72972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 73072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (daysEvents == null || daysEvents.size() == 0 || startPixel >= endPixel || 73172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson startTimeMinute < 0 || startTimeMinute > 24 * 60 || endTimeMinute < 0 || 73271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson endTimeMinute > 24 * 60 || startTimeMinute >= endTimeMinute || 73371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson segments == null || segments [0] == null || segments [1] == null) { 73472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson Log.wtf(TAG, "Illegal parameter in createBusyBitSegments, " + 73572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson "daysEvents = " + daysEvents + " , " + 73672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson "startPixel = " + startPixel + " , " + 73772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson "endPixel = " + endPixel + " , " + 73872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson "startTimeMinute = " + startTimeMinute + " , " + 73971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson "endTimeMinute = " + endTimeMinute + " , " + 74071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson "segments" + segments); 74171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return; 74272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 74372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 74472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Go over all events and create a sorted list of times that include all 74572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // the start and end times of all events. 74672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 74772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson ArrayList<BusyBitsEventTime> times = new ArrayList<BusyBitsEventTime>(); 74872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 74972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson Iterator<Event> iter = daysEvents.iterator(); 75072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Pointer to the search start in the "times" list. It prevents searching from the beginning 75172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // of the list for each event. It is updated every time a new start time is inserted into 75272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // the times list, since the events are time ordered, there is no point on searching before 75372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // the last start time that was inserted 75472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson int initialSearchIndex = 0; 75582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson while (iter.hasNext()) { 75682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson Event event = iter.next(); 75782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 75872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Take into account the start and end day. This is important for events that span 75972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // multiple days. 76072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson int eStart = event.startTime - (julianDay - event.startDay) * 24 * 60; 76172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson int eEnd = event.endTime + (event.endDay - julianDay) * 24 * 60; 76282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 76372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Skip all day events, and events that are not in the time frame 76472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (event.drawAsAllday() || eStart >= endTimeMinute || eEnd <= startTimeMinute) { 76582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson continue; 76682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 76782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 768c18dd7aea8c8ee06dd34f268ea9e0e9e7c235b7fIsaac Katzenelson // If event spans before or after start or end time , truncate it 76972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // because we care only about the time span that is passed to the function 77072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (eStart < startTimeMinute) { 77172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson eStart = startTimeMinute; 77272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 77372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (eEnd > endTimeMinute) { 77472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson eEnd = endTimeMinute; 77582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 77672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Skip events that are zero length 77772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (eStart == eEnd) { 77872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson continue; 77982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 78082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 78172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // First event , just put it in the "times" list 78272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (times.size() == 0) { 78372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson BusyBitsEventTime es = new BusyBitsEventTime(eStart, BusyBitsEventTime.EVENT_START); 78472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson BusyBitsEventTime ee = new BusyBitsEventTime(eEnd, BusyBitsEventTime.EVENT_END); 78572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson times.add(es); 78672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson times.add(ee); 78782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson continue; 78882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 78982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 79072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Insert start and end times of event in "times" list. 79172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Loop through the "times" list and put the event start and ends times in the correct 79272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // place. 79372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson boolean startInserted = false; 79472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson boolean endInserted = false; 79572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson int i = initialSearchIndex; // Skip times that are before the event time 79672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Two pointers for looping through the "times" list. Current item and next item. 79772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson int t1, t2; 79872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson do { 79972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson t1 = times.get(i).mTime; 80072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson t2 = times.get(i + 1).mTime; 80172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (!startInserted) { 80272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Start time equals an existing item in the "times" list, just update the 80372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // starts count of the specific item 80472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (eStart == t1) { 80572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson times.get(i).addStart(); 80672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson initialSearchIndex = i; 80772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson startInserted = true; 80872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } else if (eStart == t2) { 80972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson times.get(i + 1).addStart(); 81072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson initialSearchIndex = i + 1; 81172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson startInserted = true; 81272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } else if (eStart > t1 && eStart < t2) { 81372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // The start time is between the times of the current item and next item: 81472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // insert a new start time in between the items. 81572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson BusyBitsEventTime e = new BusyBitsEventTime(eStart, 81672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson BusyBitsEventTime.EVENT_START); 81772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson times.add(i + 1, e); 81872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson initialSearchIndex = i + 1; 81972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson t2 = eStart; 82072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson startInserted = true; 82172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 82282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 82372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (!endInserted) { 82472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // End time equals an existing item in the "times" list, just update the 82572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // ends count of the specific item 82672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (eEnd == t1) { 82772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson times.get(i).addEnd(); 82872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson endInserted = true; 82972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } else if (eEnd == t2) { 83072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson times.get(i + 1).addEnd(); 83172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson endInserted = true; 83272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } else if (eEnd > t1 && eEnd < t2) { 83372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // The end time is between the times of the current item and next item: 83472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // insert a new end time in between the items. 83572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson BusyBitsEventTime e = new BusyBitsEventTime(eEnd, 83672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson BusyBitsEventTime.EVENT_END); 83772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson times.add(i + 1, e); 83872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson t2 = eEnd; 83972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson endInserted = true; 84072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 84172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 84272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson i++; 84372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } while (!endInserted && i + 1 < times.size()); 84472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 84572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Deal with the last event if not inserted in the list 84672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (!startInserted) { 84772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson BusyBitsEventTime e = new BusyBitsEventTime(eStart, BusyBitsEventTime.EVENT_START); 84872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson times.add(e); 84972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson initialSearchIndex = times.size() - 1; 85072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 85172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (!endInserted) { 85272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson BusyBitsEventTime e = new BusyBitsEventTime(eEnd, BusyBitsEventTime.EVENT_END); 85372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson times.add(e); 85482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 85582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 85682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson 85772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // No events , return 85872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (times.size() == 0) { 85971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return; 86072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 86172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 86271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Loop through the created "times" list and find busy time segments and conflicting 86371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // segments. In the loop, keep the status of time (free/busy/conflicting) and the time 86472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // of when last status started. When there is a change in the status, create a segment with 86572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // the previous status from the time of the last status started until the time of the 86672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // current change. 86771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // The loop keeps a count of how many events are conflicting. Zero means free time, one 86871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // means a busy time and more than one means conflicting time. The count is updated by 86972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // the number of starts and ends from the items in the "times" list. A change is a switch 87071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // from free/busy/conflicting status to a different one. 87172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 87272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 87372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson int segmentStartTime = 0; // default start time 87471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int conflictingCount = 0; // assume starting with free time 87572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson int pixelSize = endPixel - startPixel; 87672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson int timeFrame = endTimeMinute - startTimeMinute; 87771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int prevSegmentInserted = NO_PREV_INSERTED; 87871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 87971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson 88071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Arrays are preallocated by the calling code, the first cell in the 88171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // array is the number 88271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // of already occupied cells. 88371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson float[] busySegments = segments[BUSY_ARRAY_INDEX]; 88471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson float[] conflictSegments = segments[CONFLICT_ARRAY_INDEX]; 88572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 88672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson Iterator<BusyBitsEventTime> tIter = times.iterator(); 88772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson while (tIter.hasNext()) { 88872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson BusyBitsEventTime t = tIter.next(); 88971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Get the new count of conflicting events 89071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int newCount = conflictingCount + t.mStartEndChanges; 89172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson 89271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // No need for a new segment because the free/busy/conflicting 89371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // status didn't change 89471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (conflictingCount == newCount || (conflictingCount >= 2 && newCount >= 2)) { 89571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictingCount = newCount; 89672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson continue; 89772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 89871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (conflictingCount == 0 && newCount == 1) { 89972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // A busy time started - start a new segment 90072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (segmentStartTime != 0) { 90172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Unknown status, blow up 90272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson Log.wtf(TAG, "Unknown state in createBusyBitSegments, segmentStartTime = " + 90372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson segmentStartTime + ", nolc = " + newCount); 90472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 90572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson segmentStartTime = t.mTime; 90671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } else if (conflictingCount == 0 && newCount >= 2) { 90771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // An conflicting time started - start a new segment 90872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson if (segmentStartTime != 0) { 90972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Unknown status, blow up 91072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson Log.wtf(TAG, "Unknown state in createBusyBitSegments, segmentStartTime = " + 91172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson segmentStartTime + ", nolc = " + newCount); 91272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 91372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson segmentStartTime = t.mTime; 91471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } else if (conflictingCount == 1 && newCount >= 2) { 91571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // A busy time ended and conflicting segment started, 91671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Save busy segment and start conflicting segment 91771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iBusy = 1 + (int) busySegments[COUNTER_INDEX]; 91871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson busySegments[iBusy++] = xPixel; 91971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson busySegments[iBusy++] = (segmentStartTime - startTimeMinute) * 92071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson pixelSize / timeFrame + startPixel; 92171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson busySegments[iBusy++] = xPixel; 92271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson busySegments[iBusy++] = (t.mTime - startTimeMinute) * 92371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson pixelSize / timeFrame + startPixel; 92471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Update the segments counter only after overlap correction 92571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (correctOverlappingSegment(segments, BUSY_ARRAY_INDEX, prevSegmentInserted)) { 92671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson busySegments[COUNTER_INDEX] += 4; 92771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } 92872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson segmentStartTime = t.mTime; 92971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson prevSegmentInserted = BUSY_PREV_INSERTED; 93071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } else if (conflictingCount >= 2 && newCount == 1) { 93171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // A conflicting time ended and busy segment started. 93271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Save conflicting segment and start busy segment 93371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iConflicting = 1 + (int) conflictSegments[COUNTER_INDEX]; 93471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictSegments[iConflicting++] = xPixel; 93571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictSegments[iConflicting++] = (segmentStartTime - startTimeMinute) * 93671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson pixelSize / timeFrame + startPixel; 93771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictSegments[iConflicting++] = xPixel; 93871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictSegments[iConflicting++] = (t.mTime - startTimeMinute) * 93971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson pixelSize / timeFrame + startPixel; 94071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Update the segments counter only after overlap correction 94171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (correctOverlappingSegment(segments, CONFLICT_ARRAY_INDEX, 94271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson prevSegmentInserted)) { 94371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictSegments[COUNTER_INDEX] += 4; 94471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } 94572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson segmentStartTime = t.mTime; 94671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson prevSegmentInserted = CONFLICT_PREV_INSERTED; 94771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } else if (conflictingCount >= 2 && newCount == 0) { 94871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // An conflicting segment ended, and a free time segment started 94971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Save conflicting segment 95071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iConflicting = 1 + (int) conflictSegments[COUNTER_INDEX]; 95171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictSegments[iConflicting++] = xPixel; 95271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictSegments[iConflicting++] = (segmentStartTime - startTimeMinute) * 95371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson pixelSize / timeFrame + startPixel; 95471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictSegments[iConflicting++] = xPixel; 95571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictSegments[iConflicting++] = (t.mTime - startTimeMinute) * 95671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson pixelSize / timeFrame + startPixel; 95771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Update the segments counter only after overlap correction 95871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (correctOverlappingSegment(segments, CONFLICT_ARRAY_INDEX, 95971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson prevSegmentInserted)) { 96071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictSegments[COUNTER_INDEX] += 4; 96171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } 96272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson segmentStartTime = 0; 96371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson prevSegmentInserted = CONFLICT_PREV_INSERTED; 96471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } else if (conflictingCount == 1 && newCount == 0) { 96571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // A busy segment ended, and a free time segment started, save 96671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // busy segment 96771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson int iBusy = 1 + (int) busySegments[COUNTER_INDEX]; 96871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson busySegments[iBusy++] = xPixel; 96971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson busySegments[iBusy++] = (segmentStartTime - startTimeMinute) * 97071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson pixelSize / timeFrame + startPixel; 97171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson busySegments[iBusy++] = xPixel; 97271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson busySegments[iBusy++] = (t.mTime - startTimeMinute) * 97371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson pixelSize / timeFrame + startPixel; 97471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson // Update the segments counter only after overlap correction 97571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson if (correctOverlappingSegment(segments, BUSY_ARRAY_INDEX, prevSegmentInserted)) { 97671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson busySegments[COUNTER_INDEX] += 4; 97771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson } 97872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson segmentStartTime = 0; 97971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson prevSegmentInserted = BUSY_PREV_INSERTED; 98072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } else { 98172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson // Unknown status, blow up 98272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson Log.wtf(TAG, "Unknown state in createBusyBitSegments: time = " + t.mTime + 98371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson " , olc = " + conflictingCount + " nolc = " + newCount); 98472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson } 98571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson conflictingCount = newCount; // Update count 98682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 98771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson return; 98882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson } 989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project} 990