DayView.java revision 87f993ff96172f508d3f241f8a425f953c7eb739
1146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/* 2146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Copyright (C) 2007 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 1983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chanimport com.android.calendar.CalendarController.EventType; 2083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chanimport com.android.calendar.CalendarController.ViewType; 2183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 2246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.Animator; 2346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.AnimatorListenerAdapter; 2446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.ObjectAnimator; 2546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.TypeEvaluator; 2646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.ValueAnimator; 27146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.ContentResolver; 28146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.ContentUris; 29146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context; 30146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.res.Resources; 31146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.res.TypedArray; 32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.database.Cursor; 33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Canvas; 34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Paint; 35dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.graphics.Paint.Style; 36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Rect; 37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Typeface; 38c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawaimport android.graphics.drawable.Drawable; 39146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.net.Uri; 40146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.os.Handler; 41146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.provider.Calendar.Attendees; 42146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.provider.Calendar.Calendars; 43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.provider.Calendar.Events; 443e7015267340b09d142dfcd3ff8acda257711023Shachar Shemeshimport android.text.Layout.Alignment; 45f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chanimport android.text.StaticLayout; 463e7015267340b09d142dfcd3ff8acda257711023Shachar Shemeshimport android.text.TextPaint; 47f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chanimport android.text.TextUtils; 48146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateFormat; 49146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateUtils; 50146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time; 51146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.util.Log; 52146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ContextMenu; 53dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.view.ContextMenu.ContextMenuInfo; 54ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.GestureDetector; 55146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.Gravity; 56146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.KeyEvent; 57146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.LayoutInflater; 58146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.MenuItem; 59146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.MotionEvent; 60d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chanimport android.view.ScaleGestureDetector; 61146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.View; 62146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewConfiguration; 63146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewGroup; 64146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.WindowManager; 65259b8f9a21fffd3858218581e9daaf689b6b888fErikimport android.view.accessibility.AccessibilityEvent; 6646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.view.animation.AccelerateDecelerateInterpolator; 67ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.animation.Animation; 68ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.animation.TranslateAnimation; 69146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.ImageView; 70146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.PopupWindow; 71146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.TextView; 72ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.widget.ViewSwitcher; 73146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 74146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.ArrayList; 75c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawaimport java.util.Arrays; 76146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Calendar; 77259b8f9a21fffd3858218581e9daaf689b6b888fErikimport java.util.Formatter; 78259b8f9a21fffd3858218581e9daaf689b6b888fErikimport java.util.Locale; 790d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chanimport java.util.regex.Matcher; 800d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chanimport java.util.regex.Pattern; 81146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 82146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/** 83d190418220467c02327dd9b3ae1eae238889720bMichael Chan * View for multi-day view. So far only 1 and 7 day have been tested. 84d190418220467c02327dd9b3ae1eae238889720bMichael Chan */ 85d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chanpublic class DayView extends View implements View.OnCreateContextMenuListener, 86cd405a28e6821b116dcf3c531805d0c90b6cc08cErik ScaleGestureDetector.OnScaleGestureListener, View.OnClickListener, View.OnLongClickListener 87cd405a28e6821b116dcf3c531805d0c90b6cc08cErik { 88d190418220467c02327dd9b3ae1eae238889720bMichael Chan private static String TAG = "DayView"; 89d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static boolean DEBUG = false; 90259b8f9a21fffd3858218581e9daaf689b6b888fErik private static final String HOUR_FORMAT_12H = "%A %I%p"; 91259b8f9a21fffd3858218581e9daaf689b6b888fErik private static final String HOUR_FORMAT_24H = "%A %H"; 92259b8f9a21fffd3858218581e9daaf689b6b888fErik private static final String PERIOD_SPACE = ". "; 93146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 94705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static float mScale = 0; // Used for supporting different screen densities 95666fc5e8ddbac15c951aad738bd818ee307eae42Erik private static final long INVALID_EVENT_ID = -1; //This is used for remembering a null event 96ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private static final long ANIMATION_DURATION = 400; 97705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 984484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_AGENDA = 2; 994484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_DAY = 3; 1004484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_VIEW = 5; 1014484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_CREATE = 6; 1024484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_EDIT = 7; 1034484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_DELETE = 8; 1044484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan 10511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static int DEFAULT_CELL_HEIGHT = 64; 106d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int MAX_CELL_HEIGHT = 150; 107d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int MIN_Y_SPAN = 100; 108d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mOnFlingCalled; 110666fc5e8ddbac15c951aad738bd818ee307eae42Erik /** 111666fc5e8ddbac15c951aad738bd818ee307eae42Erik * ID of the last event which was displayed with the toast popup. 112666fc5e8ddbac15c951aad738bd818ee307eae42Erik * 113666fc5e8ddbac15c951aad738bd818ee307eae42Erik * This is used to prevent popping up multiple quick views for the same event, especially 114666fc5e8ddbac15c951aad738bd818ee307eae42Erik * during calendar syncs. This becomes valid when an event is selected, either by default 115666fc5e8ddbac15c951aad738bd818ee307eae42Erik * on starting calendar or by scrolling to an event. It becomes invalid when the user 116666fc5e8ddbac15c951aad738bd818ee307eae42Erik * explicitly scrolls to an empty time slot, changes views, or deletes the event. 117666fc5e8ddbac15c951aad738bd818ee307eae42Erik */ 118666fc5e8ddbac15c951aad738bd818ee307eae42Erik private long mLastPopupEventID; 119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 120ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan protected Context mContext; 121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String[] CALENDARS_PROJECTION = new String[] { 123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Calendars._ID, // 0 124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Calendars.ACCESS_LEVEL, // 1 1256d34cec523930368976bc8d358d0a6de1da3462cMichael Chan Calendars.OWNER_ACCOUNT, // 2 126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int CALENDARS_INDEX_ACCESS_LEVEL = 1; 1286d34cec523930368976bc8d358d0a6de1da3462cMichael Chan private static final int CALENDARS_INDEX_OWNER_ACCOUNT = 2; 129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String CALENDARS_WHERE = Calendars._ID + "=%d"; 130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String[] ATTENDEES_PROJECTION = new String[] { 132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Attendees._ID, // 0 133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Attendees.ATTENDEE_RELATIONSHIP, // 1 134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int ATTENDEES_INDEX_RELATIONSHIP = 1; 136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=%d"; 137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_NONE = 0; 139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_ABOVE = 1; 140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_BELOW = 2; 141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_LEFT = 4; 142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_RIGHT = 8; 143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 144a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_NONE = 0; 145a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_DELETE = 1; 146a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_EDIT = 2; 147a505627659f6bfba8869eac8089f7030f2d0d92cErik 148d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan private static int mHorizontalSnapBackThreshold = 128; 149d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan private static int HORIZONTAL_FLING_THRESHOLD = 75; 150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ContinueScroll mContinueScroll = new ContinueScroll(); 152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Make this visible within the package for more informative debugging 154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time mBaseDate; 155bd0e834aea317236d574f8738fe11a51fdc87968Erik private Time mCurrentTime; 156bd0e834aea317236d574f8738fe11a51fdc87968Erik //Update the current time line every five minutes if the window is left open that long 157bd0e834aea317236d574f8738fe11a51fdc87968Erik private static final int UPDATE_CURRENT_TIME_DELAY = 300000; 158bd0e834aea317236d574f8738fe11a51fdc87968Erik private UpdateCurrentTime mUpdateCurrentTime = new UpdateCurrentTime(); 159bd0e834aea317236d574f8738fe11a51fdc87968Erik private int mTodayJulianDay; 160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Typeface mBold = Typeface.DEFAULT_BOLD; 162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstJulianDay; 163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mLastJulianDay; 164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMonthLength; 166487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstVisibleDate; 167487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstVisibleDayOfWeek; 168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int[] mEarliestStartHour; // indexed by the week day offset 169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean[] mHasAllDayEvent; // indexed by the week day offset 1708f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private String mAllDayString; 171259b8f9a21fffd3858218581e9daaf689b6b888fErik private String mEventCountTemplate; 172259b8f9a21fffd3858218581e9daaf689b6b888fErik 173259b8f9a21fffd3858218581e9daaf689b6b888fErik protected static StringBuilder mStringBuilder = new StringBuilder(50); 174259b8f9a21fffd3858218581e9daaf689b6b888fErik // TODO recreate formatter when locale changes 175259b8f9a21fffd3858218581e9daaf689b6b888fErik protected static Formatter mFormatter = new Formatter(mStringBuilder, Locale.getDefault()); 176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 177731f1cb808b7586b93615b408ab2636081fab0dcErik private Runnable mTZUpdater = new Runnable() { 178731f1cb808b7586b93615b408ab2636081fab0dcErik @Override 179731f1cb808b7586b93615b408ab2636081fab0dcErik public void run() { 180731f1cb808b7586b93615b408ab2636081fab0dcErik String tz = Utils.getTimeZone(mContext, this); 181731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate.timezone = tz; 182731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate.normalize(true); 183731f1cb808b7586b93615b408ab2636081fab0dcErik mCurrentTime.switchTimezone(tz); 184731f1cb808b7586b93615b408ab2636081fab0dcErik invalidate(); 185731f1cb808b7586b93615b408ab2636081fab0dcErik } 186731f1cb808b7586b93615b408ab2636081fab0dcErik }; 187731f1cb808b7586b93615b408ab2636081fab0dcErik 18846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() { 18946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 19046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void onAnimationStart(Animator animation) { 19146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = true; 19246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 19346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 19446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 19546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void onAnimationCancel(Animator animation) { 19646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = false; 19746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 19846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 19946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 20046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void onAnimationEnd(Animator animation) { 20146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = false; 20246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan resetSelectedHour(); 20346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan invalidate(); 20446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 20546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan }; 20646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * This variable helps to avoid unnecessarily reloading events by keeping 209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * track of the start millis parameter used for the most recent loading 210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * of events. If the next reload matches this, then the events are not 211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * reloaded. To force a reload, set this to zero (this is set to zero 212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * in the method clearCachedEvents()). 213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private long mLastReloadMillis; 215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ArrayList<Event> mEvents = new ArrayList<Event>(); 21708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private ArrayList<Event> mAllDayEvents = new ArrayList<Event>(); 21808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout[] mLayouts = null; 21908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout[] mAllDayLayouts = null; 220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionDay; // Julian day 221146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionHour; 222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean mSelectionAllDay; 224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2253eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan /** Width of a day or non-conflicting event */ 226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mCellWidth; 227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pre-allocate these objects and re-use them 229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mRect = new Rect(); 230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mDestRect = new Rect(); 231259b8f9a21fffd3858218581e9daaf689b6b888fErik private Rect mSelectionRect = new Rect(); 232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mPaint = new Paint(); 233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mEventTextPaint = new Paint(); 234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mSelectionPaint = new Paint(); 23502041687c35441e8a21cb763f1fc3a26525292efDavid Brown private float[] mLines; 236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 237487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstDayOfWeek; // First day of the week 238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private PopupWindow mPopup; 240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private View mPopupView; 241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The number of milliseconds to show the popup window 243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int POPUP_DISMISS_DELAY = 3000; 244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private DismissPopup mDismissPopup = new DismissPopup(); 245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mRemeasure = true; 247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private final EventLoader mEventLoader; 249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected final EventGeometry mEventGeometry; 250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2518f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static float GRID_LINE_LEFT_MARGIN = 16; 252000ba1109e2f4e527e9227fe341598ceeb3fbca6Michael Chan private static final float GRID_LINE_INNER_WIDTH = 1; 253000ba1109e2f4e527e9227fe341598ceeb3fbca6Michael Chan private static final float GRID_LINE_WIDTH = 5; 2543eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int DAY_GAP = 1; 256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int HOUR_GAP = 1; 2579c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private static int SINGLE_ALLDAY_HEIGHT = 34; 2581ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int MAX_ALLDAY_HEIGHT = 105; 259705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static int ALLDAY_TOP_MARGIN = 3; 260f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan private static int MAX_HEIGHT_OF_ONE_ALLDAY_EVENT = 34; 261e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 2628f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int HOURS_TOP_MARGIN = 2; 2638f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int HOURS_LEFT_MARGIN = 30; 2648f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int HOURS_RIGHT_MARGIN = 4; 2658f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int HOURS_MARGIN = HOURS_LEFT_MARGIN + HOURS_RIGHT_MARGIN; 266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 267bd0e834aea317236d574f8738fe11a51fdc87968Erik private static int CURRENT_TIME_LINE_HEIGHT = 2; 268bd0e834aea317236d574f8738fe11a51fdc87968Erik private static int CURRENT_TIME_LINE_BORDER_WIDTH = 1; 2691ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static final int CURRENT_TIME_LINE_SIDE_BUFFER = 2; 270bd0e834aea317236d574f8738fe11a51fdc87968Erik 271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MINUTES_PER_HOUR = 60; 272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MINUTES_PER_DAY = MINUTES_PER_HOUR * 24; 273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_MINUTE = 60 * 1000; 274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_HOUR = (3600 * 1000); 275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_DAY = MILLIS_PER_HOUR * 24; 276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 277bf4aa400663a072813c87cf9c8aaee2d07abc945Erik private static final int DAY_HEADER_ALPHA = 0x80000000; 278f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan private static final int DATE_HEADER_ALPHA = 0x26000000; 279f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan private static final int DATE_HEADER_TODAY_ALPHA = 0x99000000; 2809dd340d393575ba9740ef259e62ee7a17fc76ed1Michael Chan private static float DAY_HEADER_ONE_DAY_LEFT_MARGIN = 0; 2813eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_ONE_DAY_RIGHT_MARGIN = 5; 2823eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_ONE_DAY_BOTTOM_MARGIN = 6; 2833eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_LEFT_MARGIN = 5; 2843eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_RIGHT_MARGIN = 7; 2853eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_BOTTOM_MARGIN = 3; 2863eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_FONT_SIZE = 14; 2878f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static float DATE_HEADER_FONT_SIZE = 32; 2883eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float NORMAL_FONT_SIZE = 12; 2893eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float EVENT_TEXT_FONT_SIZE = 12; 2903eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float HOURS_FONT_SIZE = 12; 2913eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float AMPM_FONT_SIZE = 9; 2928f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int MIN_HOURS_WIDTH = 96; 293705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static int MIN_CELL_WIDTH_FOR_TEXT = 27; 294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int MAX_EVENT_TEXT_LEN = 500; 295705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static float MIN_EVENT_HEIGHT = 15.0F; // in pixels 2961ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int CALENDAR_COLOR_SQUARE_SIZE = 10; 2971ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int CALENDAR_COLOR_SQUARE_V_OFFSET = -1; 2981ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int CALENDAR_COLOR_SQUARE_H_OFFSET = -3; 2991ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_RECT_TOP_MARGIN = -1; 3001ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_RECT_BOTTOM_MARGIN = -1; 3011ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_RECT_LEFT_MARGIN = -1; 3021ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_RECT_RIGHT_MARGIN = -1; 3031ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_TEXT_TOP_MARGIN = 2; 3041ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_TEXT_BOTTOM_MARGIN = 3; 3051ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_TEXT_LEFT_MARGIN = 11; 3061ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_TEXT_RIGHT_MARGIN = 4; 3071ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_TOP_MARGIN = EVENT_TEXT_TOP_MARGIN; 3081ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN = EVENT_TEXT_BOTTOM_MARGIN; 3091ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_LEFT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 3101ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_RIGHT_MARGIN = EVENT_TEXT_RIGHT_MARGIN; 311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mPressedColor; 313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mEventTextColor; 314f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan private static int mDeclinedEventTextColor; 315f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan 31664b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok private static int mWeek_saturdayColor; 31764b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok private static int mWeek_sundayColor; 318d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarDateBannerTextColor; 3193eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarAllDayBackground; 320d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarAmPmLabel; 3213eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarDateBannerBackground; 32211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// private static int mCalendarDateSelected; 3233eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarGridAreaBackground; 324ba902466b19b11d587468e354edc58e542707747Michael Chan private static int mCalendarGridAreaSelected; 325d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarGridLineHorizontalColor; 326d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarGridLineVerticalColor; 3273eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int mCalendarGridLineInnerHorizontalColor; 3283eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int mCalendarGridLineInnerVerticalColor; 3293eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarHourBackground; 3308f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int mCalendarHourLabelColor; 33111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// private static int mCalendarHourSelected; 332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewStartX; 334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewStartY; 335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMaxViewStartY; 336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewHeight; 337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewWidth; 33846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan private int mGridAreaHeight = -1; 339d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int mCellHeight = 0; // shared among all DayViews 340d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int mMinCellHeight = 32; 341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mScrollStartY; 342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mPreviousDirection; 343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 344d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** 345d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * Vertical distance or span between the two touch points at the start of a 346d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * scaling gesture 347d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan */ 348d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private float mStartingSpanY = 0; 349d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** Height of 1 hour in pixels at the start of a scaling gesture */ 350d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private int mCellHeightBeforeScaleGesture; 351d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** The hour at the center two touch points */ 352d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private float mGestureCenterHour = 0; 353d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** 354d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * Flag to decide whether to handle the up event. Cases where up events 355d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * should be ignored are 1) right after a scale gesture and 2) finger was 356d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * down before app launch 357d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan */ 358d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private boolean mHandleActionUp = true; 359d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mHoursTextHeight; 361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mAllDayHeight; 3623eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int DAY_HEADER_HEIGHT = 45; 363f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan /** 364f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan * Max of all day events in a given day in this view. 365f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan */ 366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMaxAllDayEvents; 367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected int mNumDays = 7; 369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mNumHours = 10; 3703eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 3713eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan /** Width of the time line (list of hours) to the left. */ 372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mHoursWidth; 373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mDateStrWidth; 37446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** Top of the scrollable region i.e. below date labels and all day events */ 375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstCell; 37646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** First fully visibile hour */ 377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstHour = -1; 37846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** Distance between the mFirstCell and the top of first fully visible hour. */ 379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstHourOffset; 380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mHourStrs; 381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mDayStrs; 382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mDayStrs2Letter; 383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mIs24HourFormat; 384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ArrayList<Event> mSelectedEvents = new ArrayList<Event>(); 386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mComputeSelectedEvents; 3878307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik private boolean mUpdateToast; 388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Event mSelectedEvent; 389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Event mPrevSelectedEvent; 390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mPrevBox = new Rect(); 391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected final Resources mResources; 3923eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan protected final Drawable mCurrentTimeLine; 3933eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan protected final Drawable mTodayHeaderDrawable; 394f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan protected Drawable mAcceptedOrTentativeEventBoxDrawable; 395f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan protected Drawable mUnconfirmedOrDeclinedEventBoxDrawable; 396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String mAmString; 397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String mPmString; 398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private DeleteEventHelper mDeleteEventHelper; 3996d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private static int sCounter = 0; 400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ContextMenuHandler mContextMenuHandler = new ContextMenuHandler(); 402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 403d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan ScaleGestureDetector mScaleGestureDetector; 404d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The initial state of the touch mode when we enter this view. 407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_INITIAL_STATE = 0; 409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates we just received the touch event and we are waiting to see if 412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * it is a tap or a scroll gesture. 413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_DOWN = 1; 415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates the touch gesture is a vertical scroll 418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_VSCROLL = 0x20; 420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates the touch gesture is a horizontal scroll 423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_HSCROLL = 0x40; 425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mTouchMode = TOUCH_MODE_INITIAL_STATE; 427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The selection modes are HIDDEN, PRESSED, SELECTED, and LONGPRESS. 430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_HIDDEN = 0; 432ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan private static final int SELECTION_PRESSED = 1; // D-pad down but not up yet 433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_SELECTED = 2; 434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_LONGPRESS = 3; 435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionMode = SELECTION_HIDDEN; 437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 438146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mScrolling = false; 439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 440ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private CalendarController mController; 441ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private ViewSwitcher mViewSwitcher; 442ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private GestureDetector mGestureDetector; 443705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 444d190418220467c02327dd9b3ae1eae238889720bMichael Chan public DayView(Context context, CalendarController controller, 44575d9b567e1fd3b9c6945cd0afe28781f5a19c6c8Michael Chan ViewSwitcher viewSwitcher, EventLoader eventLoader, int numDays) { 446ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan super(context); 447705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan if (mScale == 0) { 448705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan mScale = getContext().getResources().getDisplayMetrics().density; 449705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan if (mScale != 1) { 450705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan SINGLE_ALLDAY_HEIGHT *= mScale; 451705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan ALLDAY_TOP_MARGIN *= mScale; 452f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan MAX_HEIGHT_OF_ONE_ALLDAY_EVENT *= mScale; 453705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 454705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan NORMAL_FONT_SIZE *= mScale; 455705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan EVENT_TEXT_FONT_SIZE *= mScale; 4568f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan GRID_LINE_LEFT_MARGIN *= mScale; 457705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan HOURS_FONT_SIZE *= mScale; 4588f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan HOURS_TOP_MARGIN *= mScale; 4598f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan HOURS_LEFT_MARGIN *= mScale; 4608f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan HOURS_RIGHT_MARGIN *= mScale; 4618f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan HOURS_MARGIN = HOURS_LEFT_MARGIN + HOURS_RIGHT_MARGIN; 462705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan AMPM_FONT_SIZE *= mScale; 4638f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan MIN_HOURS_WIDTH *= mScale; 464705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan MIN_CELL_WIDTH_FOR_TEXT *= mScale; 465705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan MIN_EVENT_HEIGHT *= mScale; 466705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 467d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan HORIZONTAL_FLING_THRESHOLD *= mScale; 468e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 469bd0e834aea317236d574f8738fe11a51fdc87968Erik CURRENT_TIME_LINE_HEIGHT *= mScale; 470bd0e834aea317236d574f8738fe11a51fdc87968Erik CURRENT_TIME_LINE_BORDER_WIDTH *= mScale; 471bd0e834aea317236d574f8738fe11a51fdc87968Erik 472d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan MIN_Y_SPAN *= mScale; 473d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan MAX_CELL_HEIGHT *= mScale; 474697157470a6f0d8e7b806af9b4fb7fbe0bccae87Erik DEFAULT_CELL_HEIGHT *= mScale; 4753eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_HEIGHT *= mScale; 4763eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_LEFT_MARGIN *= mScale; 4773eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_RIGHT_MARGIN *= mScale; 4783eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_BOTTOM_MARGIN *= mScale; 4793eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_LEFT_MARGIN *= mScale; 4803eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_RIGHT_MARGIN *= mScale; 4813eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_BOTTOM_MARGIN *= mScale; 4823eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_FONT_SIZE *= mScale; 4833eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DATE_HEADER_FONT_SIZE *= mScale; 4843eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan CALENDAR_COLOR_SQUARE_SIZE *= mScale; 4853eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_TOP_MARGIN *= mScale; 4863eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_BOTTOM_MARGIN *= mScale; 4873eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_LEFT_MARGIN *= mScale; 4883eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_RIGHT_MARGIN *= mScale; 4899c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_TOP_MARGIN *= mScale; 4909c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN *= mScale; 4919c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_LEFT_MARGIN *= mScale; 4929c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_RIGHT_MARGIN *= mScale; 49311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_TOP_MARGIN *= mScale; 49411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_BOTTOM_MARGIN *= mScale; 49511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_LEFT_MARGIN *= mScale; 49611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_RIGHT_MARGIN *= mScale; 497705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan } 498705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan } 499705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 500ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mResources = context.getResources(); 5013eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine = mResources.getDrawable(R.drawable.timeline_week_holo_light); 5023eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable = mResources.getDrawable(R.drawable.today_blue_week_holo_light); 503f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan mAcceptedOrTentativeEventBoxDrawable = mResources 504f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan .getDrawable(R.drawable.panel_month_event_holo_light); 505f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan mUnconfirmedOrDeclinedEventBoxDrawable = mResources 506f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan .getDrawable(R.drawable.week_event_bg_decline_holo_light); 507ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mEventLoader = eventLoader; 508146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry = new EventGeometry(); 509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setMinEventHeight(MIN_EVENT_HEIGHT); 510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setHourGap(HOUR_GAP); 511ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mContext = context; 5128f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mAllDayString = mContext.getString(R.string.edit_event_all_day_label); 513ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mDeleteEventHelper = new DeleteEventHelper(context, null, false /* don't exit when done */); 514666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 515ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mController = controller; 516ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher = viewSwitcher; 517ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector = new GestureDetector(context, new CalendarGestureListener()); 518d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mScaleGestureDetector = new ScaleGestureDetector(getContext(), this); 51975d9b567e1fd3b9c6945cd0afe28781f5a19c6c8Michael Chan mNumDays = numDays; 520d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight == 0) { 521d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = Utils.getSharedPreference(mContext, 522d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan GeneralPreferences.KEY_DEFAULT_CELL_HEIGHT, DEFAULT_CELL_HEIGHT); 523d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 524146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 525ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan init(context); 526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void init(Context context) { 529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setFocusable(true); 530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allow focus in touch mode so that we can do keyboard shortcuts 532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // even after we've entered touch mode. 533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setFocusableInTouchMode(true); 534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setClickable(true); 535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setOnCreateContextMenuListener(this); 536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 537487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstDayOfWeek = Utils.getFirstDayOfWeek(context); 538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 539731f1cb808b7586b93615b408ab2636081fab0dcErik mCurrentTime = new Time(Utils.getTimeZone(context, mTZUpdater)); 540bd0e834aea317236d574f8738fe11a51fdc87968Erik long currentTime = System.currentTimeMillis(); 541bd0e834aea317236d574f8738fe11a51fdc87968Erik mCurrentTime.set(currentTime); 542bd0e834aea317236d574f8738fe11a51fdc87968Erik //The % makes it go off at the next increment of 5 minutes. 543bd0e834aea317236d574f8738fe11a51fdc87968Erik postDelayed(mUpdateCurrentTime, 544bd0e834aea317236d574f8738fe11a51fdc87968Erik UPDATE_CURRENT_TIME_DELAY - (currentTime % UPDATE_CURRENT_TIME_DELAY)); 545bd0e834aea317236d574f8738fe11a51fdc87968Erik mTodayJulianDay = Time.getJulianDay(currentTime, mCurrentTime.gmtoff); 546bd0e834aea317236d574f8738fe11a51fdc87968Erik 54764b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok mWeek_saturdayColor = mResources.getColor(R.color.week_saturday); 54864b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok mWeek_sundayColor = mResources.getColor(R.color.week_sunday); 549d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarDateBannerTextColor = mResources.getColor(R.color.calendar_date_banner_text_color); 5503eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarAllDayBackground = mResources.getColor(R.color.calendar_all_day_background); 551d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarAmPmLabel = mResources.getColor(R.color.calendar_ampm_label); 5523eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarDateBannerBackground = mResources.getColor(R.color.calendar_date_banner_background); 55311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// mCalendarDateSelected = mResources.getColor(R.color.calendar_date_selected); 5543eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarGridAreaBackground = mResources.getColor(R.color.calendar_grid_area_background); 555ba902466b19b11d587468e354edc58e542707747Michael Chan mCalendarGridAreaSelected = mResources.getColor(R.color.calendar_grid_area_selected); 556d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarGridLineHorizontalColor = mResources.getColor(R.color.calendar_grid_line_horizontal_color); 557d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarGridLineVerticalColor = mResources.getColor(R.color.calendar_grid_line_vertical_color); 5583eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCalendarGridLineInnerHorizontalColor = mResources.getColor(R.color.calendar_grid_line_inner_horizontal_color); 5593eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCalendarGridLineInnerVerticalColor = mResources.getColor(R.color.calendar_grid_line_inner_vertical_color); 5603eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarHourBackground = mResources.getColor(R.color.calendar_hour_background); 5618f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mCalendarHourLabelColor = mResources.getColor(R.color.calendar_hour_label); 56211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// mCalendarHourSelected = mResources.getColor(R.color.calendar_hour_selected); 563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPressedColor = mResources.getColor(R.color.pressed); 564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextColor = mResources.getColor(R.color.calendar_event_text_color); 565f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan mDeclinedEventTextColor = mResources.getColor(R.color.calendar_declined_event_text_color); 56611638ad4fb56b978770aebe75deac7a0e6ac60d2Erik 567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setTextSize(EVENT_TEXT_FONT_SIZE); 568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setTextAlign(Paint.Align.LEFT); 569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setAntiAlias(true); 570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int gridLineColor = mResources.getColor(R.color.calendar_grid_line_highlight_color); 572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mSelectionPaint; 573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setColor(gridLineColor); 5743937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setStyle(Style.FILL); 575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p = mPaint; 578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allocate space for 2 weeks worth of weekday names so that we can 581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // easily start the week display at any week day. 582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs = new String[14]; 583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also create an array of 2-letter abbreviations. 585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter = new String[14]; 586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) { 588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int index = i - Calendar.SUNDAY; 589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // e.g. Tue for Tuesday 590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_MEDIUM); 591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs[index + 7] = mDayStrs[index]; 592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // e.g. Tu for Tuesday 593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_SHORT); 59452b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer 59552b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer // If we don't have 2-letter day strings, fall back to 1-letter. 59652b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer if (mDayStrs2Letter[index].equals(mDayStrs[index])) { 59752b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer mDayStrs2Letter[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_SHORTEST); 59852b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer } 59952b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer 600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter[index + 7] = mDayStrs2Letter[index]; 601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out how much space we need for the 3-letter abbrev names 604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // in the worst case. 6053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] dateStrs = {" 28", " 30"}; 608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDateStrWidth = computeMaxStringWidth(0, dateStrs, p); 6093eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDateStrWidth += computeMaxStringWidth(0, mDayStrs, p); 611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(HOURS_FONT_SIZE); 613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(null); 61461a2e87e7412281d17e86ccff4352cbf32fe77e7Michael Chan handleOnResume(); 615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAmString = DateUtils.getAMPMString(Calendar.AM); 617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPmString = DateUtils.getAMPMString(Calendar.PM); 618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] ampm = {mAmString, mPmString}; 619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(AMPM_FONT_SIZE); 6208f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mHoursWidth = computeMaxStringWidth(mHoursWidth, ampm, p) + HOURS_MARGIN; 6218f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mHoursWidth = Math.max(MIN_HOURS_WIDTH, mHoursWidth); 622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project LayoutInflater inflater; 624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView = inflater.inflate(R.layout.bubble_event, null); 626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView.setLayoutParams(new ViewGroup.LayoutParams( 627df279e3f9d5b0f189f812c52aca78d18178e4445Romain Guy ViewGroup.LayoutParams.MATCH_PARENT, 628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ViewGroup.LayoutParams.WRAP_CONTENT)); 629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup = new PopupWindow(context); 630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setContentView(mPopupView); 631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Resources.Theme dialogTheme = getResources().newTheme(); 632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dialogTheme.applyStyle(android.R.style.Theme_Dialog, true); 633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TypedArray ta = dialogTheme.obtainStyledAttributes(new int[] { 634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project android.R.attr.windowBackground }); 635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setBackgroundDrawable(ta.getDrawable(0)); 636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ta.recycle(); 637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Enable touching the popup window 639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView.setOnClickListener(this); 640cd405a28e6821b116dcf3c531805d0c90b6cc08cErik // Catch long clicks for creating a new event 641cd405a28e6821b116dcf3c531805d0c90b6cc08cErik setOnLongClickListener(this); 642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 643731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate = new Time(Utils.getTimeZone(context, mTZUpdater)); 644146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = System.currentTimeMillis(); 645146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.set(millis); 646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 647146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour = new int[mNumDays]; 648146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent = new boolean[mNumDays]; 64902041687c35441e8a21cb763f1fc3a26525292efDavid Brown 65002041687c35441e8a21cb763f1fc3a26525292efDavid Brown // mLines is the array of points used with Canvas.drawLines() in 65102041687c35441e8a21cb763f1fc3a26525292efDavid Brown // drawGridBackground() and drawAllDayEvents(). Its size depends 65202041687c35441e8a21cb763f1fc3a26525292efDavid Brown // on the max number of lines that can ever be drawn by any single 65302041687c35441e8a21cb763f1fc3a26525292efDavid Brown // drawLines() call in either of those methods. 65402041687c35441e8a21cb763f1fc3a26525292efDavid Brown final int maxGridLines = (24 + 1) // max horizontal lines we might draw 65502041687c35441e8a21cb763f1fc3a26525292efDavid Brown + (mNumDays + 1); // max vertical lines we might draw 65602041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines = new float[maxGridLines * 4]; 657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 658146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 659146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * This is called when the popup window is pressed. 661146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 662146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void onClick(View v) { 663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (v == mPopupView) { 664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pretend it was a trackball click because that will always 665146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // jump to the "View event" screen. 666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball */); 667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 668146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 67061a2e87e7412281d17e86ccff4352cbf32fe77e7Michael Chan public void handleOnResume() { 671ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mIs24HourFormat = DateFormat.is24HourFormat(mContext); 67269ab334d6988eda70ba53618506d23ebf7d7b405Erik mHourStrs = mIs24HourFormat ? CalendarData.s24Hours : CalendarData.s12HoursNoAmPm; 67361a2e87e7412281d17e86ccff4352cbf32fe77e7Michael Chan mFirstDayOfWeek = Utils.getFirstDayOfWeek(mContext); 67469ab334d6988eda70ba53618506d23ebf7d7b405Erik } 67569ab334d6988eda70ba53618506d23ebf7d7b405Erik 676146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 677146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Returns the start of the selected time in milliseconds since the epoch. 678146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 679146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return selected time in UTC milliseconds since the epoch. 680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long getSelectedTimeInMillis() { 682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 685146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 686146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 687146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 688146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 689146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time.normalize(true /* ignore isDst */); 690146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 691146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 692146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time getSelectedTime() { 693146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 694146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 695146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 696146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 697146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 698146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 699146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 700146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.normalize(true /* ignore isDst */); 701146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time; 702146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 703146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 704146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 705146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Returns the start of the selected time in minutes since midnight, 706146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * local time. The derived class must ensure that this is consistent 707146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * with the return value from getSelectedTimeInMillis(). 708146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 709146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int getSelectedMinutesSinceMidnight() { 710146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return mSelectionHour * MINUTES_PER_HOUR; 711146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 712146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 71346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int getFirstVisibleHour() { 71446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return mFirstHour; 71546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 71646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 71746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan void setFirstVisibleHour(int firstHour) { 71846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mFirstHour = firstHour; 71946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mFirstHourOffset = 0; 72046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 72146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 72246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void setSelected(Time time, boolean ignoreTime) { 723146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.set(time); 724146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mBaseDate.hour; 725146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 726146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 727146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = mBaseDate.toMillis(false /* use isDst */); 728146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = Time.getJulianDay(millis, mBaseDate.gmtoff); 729146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 730146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 731146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 73246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int gotoY = Integer.MIN_VALUE; 73346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 73446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (!ignoreTime && mGridAreaHeight != -1) { 73546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int lastHour = 0; 73646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 73746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mBaseDate.hour < mFirstHour) { 73846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Above visible region 73946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan gotoY = mBaseDate.hour * (mCellHeight + HOUR_GAP); 74046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 74146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan lastHour = (mGridAreaHeight - mFirstHourOffset) / (mCellHeight + HOUR_GAP) 74246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan + mFirstHour; 74346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 74446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mBaseDate.hour >= lastHour) { 74546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Below visible region 74646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 74746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // target hour + 1 (to give it room to see the event) - 74846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // grid height (to get the y of the top of the visible 74946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // region) 75055a26d7062d5aa1a1b001b7271bb137276ab807eErik gotoY = (int) ((mBaseDate.hour + 1 + mBaseDate.minute / 60.0f) 75146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * (mCellHeight + HOUR_GAP) - mGridAreaHeight); 75246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 75346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 75446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 75546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) { 75646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan Log.e(TAG, "Go " + gotoY + " 1st " + mFirstHour + ":" + mFirstHourOffset + "CH " 75746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan + (mCellHeight + HOUR_GAP) + " lh " + lastHour + " gh " + mGridAreaHeight 75846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan + " ymax " + mMaxViewStartY); 75946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 76046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 76146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (gotoY > mMaxViewStartY) { 76246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan gotoY = mMaxViewStartY; 76346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else if (gotoY < 0 && gotoY != Integer.MIN_VALUE) { 76446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan gotoY = 0; 76546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 76646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 76746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 768146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 769146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 770ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan // Don't draw the selection box if we are going to the "current" time 771ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan long currMillis = System.currentTimeMillis(); 772ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan boolean recent = (currMillis - 10000) < millis && millis < currMillis; 77346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectionMode = (recent || ignoreTime) ? SELECTION_HIDDEN : SELECTION_SELECTED; 774146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = true; 775146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 77646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 77746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (gotoY != Integer.MIN_VALUE) { 77846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan TypeEvaluator evaluator = new TypeEvaluator() { 77946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 78046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public Object evaluate(float fraction, Object startValue, Object endValue) { 78146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int start = (Integer) startValue; 78246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int end = (Integer) endValue; 78346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan final int newValue = (int) ((end - start) * fraction + start); 78446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan setViewStartY(newValue); 78546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return new Integer(newValue); 78646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 78746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan }; 78846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan ValueAnimator scrollAnim = ObjectAnimator.ofObject(evaluator, new Integer(mViewStartY), 78946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan new Integer(gotoY)); 79046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// TODO The following line is supposed to replace the two statements above. 79146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// Need to investigate why it's not working. 79246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 79346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// ValueAnimator scrollAnim = ObjectAnimator.ofInt(this, "viewStartY", mViewStartY, gotoY); 79446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan scrollAnim.setDuration(200); 79546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan scrollAnim.setInterpolator(new AccelerateDecelerateInterpolator()); 79646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan scrollAnim.addListener(mAnimatorListener); 79746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan scrollAnim.start(); 79846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 79946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 80046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 80146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void setViewStartY(int viewStartY) { 80246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (viewStartY > mMaxViewStartY) { 80346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan viewStartY = mMaxViewStartY; 80446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 80546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 80646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mViewStartY = viewStartY; 80746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 80846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan computeFirstHour(); 80946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan invalidate(); 810146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 811146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 812146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public Time getSelectedDay() { 813146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 814146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 815146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 816146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 817146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 818146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 819146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.normalize(true /* ignore isDst */); 821146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time; 822146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 823146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 824eaafa2b48be7194a61754604ae37b3d62e9118d8Erik public void updateTitle() { 825eaafa2b48be7194a61754604ae37b3d62e9118d8Erik Time start = new Time(mBaseDate); 826eaafa2b48be7194a61754604ae37b3d62e9118d8Erik start.normalize(true); 827eaafa2b48be7194a61754604ae37b3d62e9118d8Erik Time end = new Time(start); 828eaafa2b48be7194a61754604ae37b3d62e9118d8Erik end.monthDay += mNumDays - 1; 829eaafa2b48be7194a61754604ae37b3d62e9118d8Erik // Move it forward one minute so the formatter doesn't lose a day 830eaafa2b48be7194a61754604ae37b3d62e9118d8Erik end.minute += 1; 831eaafa2b48be7194a61754604ae37b3d62e9118d8Erik end.normalize(true); 832eaafa2b48be7194a61754604ae37b3d62e9118d8Erik 8339e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan long formatFlags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR; 8349e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan if (mNumDays != 1) { 8359e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan // Don't show day of the month if for multi-day view 8369e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan formatFlags |= DateUtils.FORMAT_NO_MONTH_DAY; 8379e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan 8389e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan // Abbreviate the month if showing multiple months 8399e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan if (start.month != end.month) { 8409e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan formatFlags |= DateUtils.FORMAT_ABBREV_MONTH; 8419e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan } 8429e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan } 8439e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan 844f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mController.sendEvent(this, EventType.UPDATE_TITLE, start, end, null, -1, ViewType.CURRENT, 8459e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan formatFlags, null, null); 846eaafa2b48be7194a61754604ae37b3d62e9118d8Erik } 847eaafa2b48be7194a61754604ae37b3d62e9118d8Erik 84883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan /** 849487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * return a negative number if "time" is comes before the visible time 850487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * range, a positive number if "time" is after the visible time range, and 0 851487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * if it is in the visible time range. 85283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan */ 853487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan public int compareToVisibleTimeRange(Time time) { 854487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 855487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedHour = mBaseDate.hour; 856487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedMinute = mBaseDate.minute; 857487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedSec = mBaseDate.second; 858487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 859487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.hour = 0; 860487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.minute = 0; 861487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.second = 0; 862487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 863030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) { 864030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown Log.d(TAG, "Begin " + mBaseDate.toString()); 865030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown Log.d(TAG, "Diff " + time.toString()); 866030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown } 867487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 86883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan // Compare beginning of range 86983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan int diff = Time.compare(time, mBaseDate); 870487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (diff > 0) { 871487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // Compare end of range 872487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.monthDay += mNumDays; 873487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.normalize(true); 874487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = Time.compare(time, mBaseDate); 875487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 876030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "End " + mBaseDate.toString()); 877487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 878487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.monthDay -= mNumDays; 879487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.normalize(true); 880487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (diff < 0) { 881487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // in visible time 882487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = 0; 883487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } else if (diff == 0) { 884487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // Midnight of following day 885487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = 1; 886487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 88783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 88883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 889030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "Diff: " + diff); 89083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 891487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.hour = savedHour; 892487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.minute = savedMinute; 893487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.second = savedSec; 894487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan return diff; 89583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 89683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 897146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void recalc() { 898146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Set the base date to the beginning of the week if we are displaying 899146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // 7 days at a time. 900146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 7) { 9016d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan adjustToBeginningOfWeek(mBaseDate); 902146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 903146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final long start = mBaseDate.toMillis(false /* use isDst */); 905146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstJulianDay = Time.getJulianDay(start, mBaseDate.gmtoff); 906146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastJulianDay = mFirstJulianDay + mNumDays - 1; 907146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 908146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mMonthLength = mBaseDate.getActualMaximum(Time.MONTH_DAY); 909487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstVisibleDate = mBaseDate.monthDay; 910487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstVisibleDayOfWeek = mBaseDate.weekDay; 911146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 912146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 9136d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private void adjustToBeginningOfWeek(Time time) { 9146d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan int dayOfWeek = time.weekDay; 9156d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan int diff = dayOfWeek - mFirstDayOfWeek; 9166d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (diff != 0) { 9176d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (diff < 0) { 9186d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan diff += 7; 9196d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 9206d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan time.monthDay -= diff; 9216d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan time.normalize(true /* ignore isDst */); 9226d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 9236d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 9246d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 925146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 926146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected void onSizeChanged(int width, int height, int oldw, int oldh) { 927146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewWidth = width; 928146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewHeight = height; 929146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int gridAreaWidth = width - mHoursWidth; 930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mCellWidth = (gridAreaWidth - (mNumDays * DAY_GAP)) / mNumDays; 931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 932d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan // This would be about 1 day worth in a 7 day view 933d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan mHorizontalSnapBackThreshold = width / 7; 934d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan 935146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = new Paint(); 936146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(HOURS_FONT_SIZE); 937146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHoursTextHeight = (int) Math.abs(p.ascent()); 938146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project remeasure(width, height); 939146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 940146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 94146b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa /** 94246b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa * Measures the space needed for various parts of the view after 94346b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa * loading new events. This can change if there are all-day events. 94446b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa */ 945146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void remeasure(int width, int height) { 946146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 947146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear the array of earliest start times, and the array 948146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // indicating presence of an all-day event. 949146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++) { 950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[day] = 25; // some big number 951146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent[day] = false; 952146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 953146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 954d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // Compute the layout relation between each event before measuring cell 955d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // width, as the cell width should be adjusted along with the relation. 95646b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // 95746b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // Examples: A (1:00pm - 1:01pm), B (1:02pm - 2:00pm) 95846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // We should mark them as "overwapped". Though they are not overwapped logically, but 95946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // minimum cell height implicitly expands the cell height of A and it should look like 96046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // (1:00pm - 1:15pm) after the cell height adjustment. 96146b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa 962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the space needed for the all-day events, if any. 963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Make a pass over all the events, and keep track of the maximum 964146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // number of all-day events in any one day. Also, keep track of 965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the earliest event in each day. 966146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxAllDayEvents = 0; 96746b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final ArrayList<Event> events = mEvents; 96846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final int len = events.size(); 969c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa // Num of all-day-events on each day. 970c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int eventsCount[] = new int[mLastJulianDay - mFirstJulianDay + 1]; 971c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa Arrays.fill(eventsCount, 0); 972146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 973146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(ii); 974c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (event.startDay > mLastJulianDay || event.endDay < mFirstJulianDay) { 975146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 976c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 977d031419da7900dab91ac9f512374d7e59bb74dceErik if (event.drawAsAllDay()) { 978c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int firstDay = Math.max(event.startDay, mFirstJulianDay); 979c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int lastDay = Math.min(event.endDay, mLastJulianDay); 980c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa for (int day = firstDay; day <= lastDay; day++) { 981c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int count = ++eventsCount[day - mFirstJulianDay]; 982c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (maxAllDayEvents < count) { 983c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa maxAllDayEvents = count; 984c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 985146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 986c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa 987146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = event.startDay - mFirstJulianDay; 988146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int durationDays = event.endDay - event.startDay + 1; 989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum < 0) { 990146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project durationDays += daynum; 991146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project daynum = 0; 992146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum + durationDays > mNumDays) { 994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project durationDays = mNumDays - daynum; 995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = daynum; durationDays > 0; day++, durationDays--) { 997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent[day] = true; 998146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1000146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = event.startDay - mFirstJulianDay; 1001146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int hour = event.startTime / 60; 1002146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum >= 0 && hour < mEarliestStartHour[daynum]) { 1003146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[daynum] = hour; 1004146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1005146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1006146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also check the end hour in case the event spans more than 1007146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // one day. 1008146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project daynum = event.endDay - mFirstJulianDay; 1009146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project hour = event.endTime / 60; 1010146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum < mNumDays && hour < mEarliestStartHour[daynum]) { 1011146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[daynum] = hour; 1012146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1013146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1014146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1015146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mMaxAllDayEvents = maxAllDayEvents; 1016146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 10179c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan // Calculate mAllDayHeight 10183eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mFirstCell = DAY_HEADER_HEIGHT; 1019146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int allDayHeight = 0; 1020146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxAllDayEvents > 0) { 1021146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is at most one all-day event per day, then use less 1022146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // space (but more than the space for a single event). 1023146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxAllDayEvents == 1) { 1024146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project allDayHeight = SINGLE_ALLDAY_HEIGHT; 1025146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1026146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allow the all-day area to grow in height depending on the 1027146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // number of all-day events we need to show, up to a limit. 1028f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan allDayHeight = maxAllDayEvents * MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 1029146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (allDayHeight > MAX_ALLDAY_HEIGHT) { 1030146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project allDayHeight = MAX_ALLDAY_HEIGHT; 1031146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1032146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 10333eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mFirstCell = DAY_HEADER_HEIGHT + allDayHeight + ALLDAY_TOP_MARGIN; 1034146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1035146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = false; 1036146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1037146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAllDayHeight = allDayHeight; 1038146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1039146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mGridAreaHeight = height - mFirstCell; 1040d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 1041d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // The min is where 24 hours cover the entire visible area 104246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mMinCellHeight = (height - DAY_HEADER_HEIGHT) / 24; 1043d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight < mMinCellHeight) { 1044d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = mMinCellHeight; 1045d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 1046d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 104746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mNumHours = mGridAreaHeight / (mCellHeight + HOUR_GAP); 1048146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setHourHeight(mCellHeight); 1049146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 105027d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa final long minimumDurationMillis = (long) 105127d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa (MIN_EVENT_HEIGHT * DateUtils.MINUTE_IN_MILLIS / (mCellHeight / 60.0f)); 105246b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa Event.computePositions(events, minimumDurationMillis); 105346b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa 1054c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Compute the top of our reachable view 1055c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mMaxViewStartY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP) - mGridAreaHeight; 1056d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 1057d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.e(TAG, "mViewStartY: " + mViewStartY); 1058d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.e(TAG, "mMaxViewStartY: " + mMaxViewStartY); 1059d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 1060d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mViewStartY > mMaxViewStartY) { 1061d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = mMaxViewStartY; 1062d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan computeFirstHour(); 1063d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 1064146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1065146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour == -1) { 1066146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initFirstHour(); 1067146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = 0; 1068146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1069146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1070146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // When we change the base date, the number of all-day events may 1071146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // change and that changes the cell height. When we switch dates, 1072146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // we use the mFirstHourOffset from the previous view, but that may 1073146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // be too large for the new view if the cell height is smaller. 1074146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHourOffset >= mCellHeight + HOUR_GAP) { 1075146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = mCellHeight + HOUR_GAP - 1; 1076146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mFirstHour * (mCellHeight + HOUR_GAP) - mFirstHourOffset; 1078146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 107946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final int eventAreaWidth = mNumDays * (mCellWidth + DAY_GAP); 1080666fc5e8ddbac15c951aad738bd818ee307eae42Erik //When we get new events we don't want to dismiss the popup unless the event changes 1081666fc5e8ddbac15c951aad738bd818ee307eae42Erik if (mSelectedEvent != null && mLastPopupEventID != mSelectedEvent.id) { 1082666fc5e8ddbac15c951aad738bd818ee307eae42Erik mPopup.dismiss(); 1083666fc5e8ddbac15c951aad738bd818ee307eae42Erik } 1084146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setWidth(eventAreaWidth - 20); 1085146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); 1086146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1087146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1088146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1089146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Initialize the state for another view. The given view is one that has 1090146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * its own bitmap and will use an animation to replace the current view. 1091146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The current view and new view are either both Week views or both Day 1092146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * views. They differ in their base date. 1093146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 1094146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param view the view to initialize. 1095146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1096d190418220467c02327dd9b3ae1eae238889720bMichael Chan private void initView(DayView view) { 1097146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionHour = mSelectionHour; 1098146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectedEvents.clear(); 1099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mComputeSelectedEvents = true; 1100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mFirstHour = mFirstHour; 1101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mFirstHourOffset = mFirstHourOffset; 1102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.remeasure(getWidth(), getHeight()); 1103e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 1104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectedEvent = null; 1105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mPrevSelectedEvent = null; 1106487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan view.mFirstDayOfWeek = mFirstDayOfWeek; 1107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (view.mEvents.size() > 0) { 1108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionAllDay = mSelectionAllDay; 1109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionAllDay = false; 1111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Redraw the screen so that the selection box will be redrawn. We may 1114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // have scrolled to a different part of the day in some other view 1115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // so the selection box in this view may no longer be visible. 1116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.recalc(); 1117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Switch to another view based on what was selected (an event or a free 1121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * slot) and how it was selected (by touch or by trackball). 1122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 1123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param trackBallSelection true if the selection was made using the 1124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * trackball. 1125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void switchViews(boolean trackBallSelection) { 1127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 1128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 1130666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays > 1) { 1132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the Week view. 1133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // With touch, we always switch to Day/Agenda View 1134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // With track ball, if we selected a free slot, then create an event. 1135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected a specific event, switch to EventInfo view. 1136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (trackBallSelection) { 1137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 1138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EditEvent view 1139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 1140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 11419e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 114287f993ff96172f508d3f241f8a425f953c7eb739RoboErik startMillis, endMillis, 0, 0, -1); 1143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EventInfo view 11459e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 114687f993ff96172f508d3f241f8a425f953c7eb739RoboErik selectedEvent.startMillis, selectedEvent.endMillis, 0, 0, 114787f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis()); 1148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This was a touch selection. If the touch selected a single 1151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // unambiguous event, then view that event. Otherwise go to 1152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Day/Agenda view. 1153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvents.size() == 1) { 11549e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 115587f993ff96172f508d3f241f8a425f953c7eb739RoboErik selectedEvent.startMillis, selectedEvent.endMillis, 0, 0, 115687f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis()); 1157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the Day view. 1161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected a free slot, then create an event. 1162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected an event, then go to the EventInfo view. 1163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 1164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EditEvent view 1165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 1166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 11679e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan 11689e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, startMillis, 116987f993ff96172f508d3f241f8a425f953c7eb739RoboErik endMillis, 0, 0, -1); 1170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 11719e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 117287f993ff96172f508d3f241f8a425f953c7eb739RoboErik selectedEvent.startMillis, selectedEvent.endMillis, 0, 0, 117387f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis()); 1174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 1180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 1181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long duration = event.getEventTime() - event.getDownTime(); 1182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (keyCode) { 1184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 1185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_HIDDEN) { 1186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Don't do anything unless the selection is visible. 1187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_PRESSED) { 1191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This was the first press when there was nothing selected. 1192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Change the selection from the "pressed" state to the 1193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the "selected" state. We treat short-press and 1194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // long-press the same here because nothing was selected. 1195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check the duration to determine if this was a short press 1201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (duration < ViewConfiguration.getLongPressTimeout()) { 1202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball */); 1203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 1205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project performLongClick(); 1207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1209ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// case KeyEvent.KEYCODE_BACK: 1210ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// if (event.isTracking() && !event.isCanceled()) { 1211ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mPopup.dismiss(); 1212ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.finish(); 1213ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// return true; 1214ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// } 1215ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// break; 1216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyUp(keyCode, event); 1218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1221146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 1222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_HIDDEN) { 1223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT 1224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_UP 1225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { 1226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Display the selection box but don't move or select it 1227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on this key press. 1228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 1232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Display the selection box but don't select it 1233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on this key press. 1234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_PRESSED; 1235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 1242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean redraw; 1243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectionDay = mSelectionDay; 1244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (keyCode) { 124646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DEL: 124746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Delete the selected event, if any 124846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan Event selectedEvent = mSelectedEvent; 124946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (selectedEvent == null) { 125046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return false; 125146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 125246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mPopup.dismiss(); 125346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 1254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 125546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan long begin = selectedEvent.startMillis; 125646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan long end = selectedEvent.endMillis; 125746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan long id = selectedEvent.id; 125846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mDeleteEventHelper.delete(begin, end, id, -1); 1259b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan return true; 126046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_ENTER: 126146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan switchViews(true /* trackball or keyboard */); 126246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 126346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_BACK: 126446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (event.getRepeatCount() == 0) { 126546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan event.startTracking(); 126646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 126746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 126846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return super.onKeyDown(keyCode, event); 126946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_LEFT: 127046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 127146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvent = mSelectedEvent.nextLeft; 127246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 127346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 127446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 127546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan selectionDay -= 1; 127646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 127746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 127846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 128046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_RIGHT: 128146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 128246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvent = mSelectedEvent.nextRight; 128346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 128446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 128546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 128646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan selectionDay += 1; 128746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 128846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 128946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 129146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_UP: 129246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 129346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvent = mSelectedEvent.nextUp; 1294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 129546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 129646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 129746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (!mSelectionAllDay) { 129846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectionHour -= 1; 129946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan adjustHourSelection(); 130046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvents.clear(); 130146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mComputeSelectedEvents = true; 130246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 130346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 130446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 130546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 130746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_DOWN: 130846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 130946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvent = mSelectedEvent.nextDown; 1310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 131146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 131246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 131346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectionAllDay) { 131446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectionAllDay = false; 131546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 131646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectionHour++; 131746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan adjustHourSelection(); 131846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvents.clear(); 131946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mComputeSelectedEvents = true; 132046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 132146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 132246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 132346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 132546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan default: 132646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return super.onKeyDown(keyCode, event); 1327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((selectionDay < mFirstJulianDay) || (selectionDay > mLastJulianDay)) { 1330d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getNextView(); 1331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time date = view.mBaseDate; 1332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.set(mBaseDate); 1333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectionDay < mFirstJulianDay) { 1334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay -= mNumDays; 1335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay += mNumDays; 1337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.normalize(true /* ignore isDst */); 1339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = selectionDay; 1340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initView(view); 134283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 134383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time end = new Time(date); 134483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan end.monthDay += mNumDays - 1; 134583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Log.d(TAG, "onKeyDown"); 13463458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan mController.sendEvent(this, EventType.GO_TO, date, end, -1, ViewType.CURRENT); 1347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 134904b288958078f8b29870dcbb2239df448c559610Erik if (mSelectionDay != selectionDay) { 135004b288958078f8b29870dcbb2239df448c559610Erik Time date = new Time(mBaseDate); 135104b288958078f8b29870dcbb2239df448c559610Erik date.setJulianDay(selectionDay); 135204b288958078f8b29870dcbb2239df448c559610Erik date.hour = mSelectionHour; 135304b288958078f8b29870dcbb2239df448c559610Erik mController.sendEvent(this, EventType.GO_TO, date, date, -1, ViewType.CURRENT); 135404b288958078f8b29870dcbb2239df448c559610Erik } 1355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = selectionDay; 1356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 13588307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik mUpdateToast = true; 1359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (redraw) { 1361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyDown(keyCode, event); 1366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1368259b8f9a21fffd3858218581e9daaf689b6b888fErik private class AccessibilityRunnable implements Runnable { 1369259b8f9a21fffd3858218581e9daaf689b6b888fErik int mEventType = AccessibilityEvent.TYPE_VIEW_SELECTED; 1370259b8f9a21fffd3858218581e9daaf689b6b888fErik @Override 1371259b8f9a21fffd3858218581e9daaf689b6b888fErik public void run() { 1372259b8f9a21fffd3858218581e9daaf689b6b888fErik sendAccessibilityEvent(mEventType); 1373259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1374259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1375259b8f9a21fffd3858218581e9daaf689b6b888fErik 1376259b8f9a21fffd3858218581e9daaf689b6b888fErik private AccessibilityRunnable mDispatchAccessibilityEventRunnable = new AccessibilityRunnable(); 1377259b8f9a21fffd3858218581e9daaf689b6b888fErik 1378259b8f9a21fffd3858218581e9daaf689b6b888fErik @Override 1379259b8f9a21fffd3858218581e9daaf689b6b888fErik public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 1380259b8f9a21fffd3858218581e9daaf689b6b888fErik if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SELECTED && 1381259b8f9a21fffd3858218581e9daaf689b6b888fErik event.getEventType() != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) { 1382259b8f9a21fffd3858218581e9daaf689b6b888fErik return false; 1383259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1384259b8f9a21fffd3858218581e9daaf689b6b888fErik StringBuilder b = new StringBuilder(getSelectedTime() 1385259b8f9a21fffd3858218581e9daaf689b6b888fErik .format(mIs24HourFormat ? HOUR_FORMAT_24H : HOUR_FORMAT_12H)); 1386259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(PERIOD_SPACE); 1387259b8f9a21fffd3858218581e9daaf689b6b888fErik int numEvents = mSelectedEvents.size(); 1388259b8f9a21fffd3858218581e9daaf689b6b888fErik if (mEventCountTemplate == null) { 1389259b8f9a21fffd3858218581e9daaf689b6b888fErik mEventCountTemplate = mContext.getString(R.string.template_announce_item_index); 1390259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1391259b8f9a21fffd3858218581e9daaf689b6b888fErik switch (event.getEventType()) { 1392259b8f9a21fffd3858218581e9daaf689b6b888fErik // When a new hour is selected we sent this event 1393259b8f9a21fffd3858218581e9daaf689b6b888fErik case AccessibilityEvent.TYPE_VIEW_SELECTED: 1394259b8f9a21fffd3858218581e9daaf689b6b888fErik int i = 1; 1395259b8f9a21fffd3858218581e9daaf689b6b888fErik for (Event calEvent : mSelectedEvents) { 1396259b8f9a21fffd3858218581e9daaf689b6b888fErik if (numEvents > 1) { 1397259b8f9a21fffd3858218581e9daaf689b6b888fErik mStringBuilder.setLength(0); 1398259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(mFormatter.format(mEventCountTemplate, i++, numEvents)); 1399259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(" "); 1400259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1401259b8f9a21fffd3858218581e9daaf689b6b888fErik appendEventAccessibilityString(b, calEvent); 1402259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1403259b8f9a21fffd3858218581e9daaf689b6b888fErik break; 1404259b8f9a21fffd3858218581e9daaf689b6b888fErik // When a different event is selected we send this event 1405259b8f9a21fffd3858218581e9daaf689b6b888fErik case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: 1406259b8f9a21fffd3858218581e9daaf689b6b888fErik if (mSelectedEvent != null) { 1407259b8f9a21fffd3858218581e9daaf689b6b888fErik if (numEvents > 1) { 1408259b8f9a21fffd3858218581e9daaf689b6b888fErik mStringBuilder.setLength(0); 1409259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(mFormatter.format(mEventCountTemplate, 1410259b8f9a21fffd3858218581e9daaf689b6b888fErik mSelectedEvents.indexOf(mSelectedEvent) + 1, numEvents)); 1411259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(" "); 1412259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1413259b8f9a21fffd3858218581e9daaf689b6b888fErik appendEventAccessibilityString(b, mSelectedEvent); 1414259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1415259b8f9a21fffd3858218581e9daaf689b6b888fErik break; 1416259b8f9a21fffd3858218581e9daaf689b6b888fErik default: 1417259b8f9a21fffd3858218581e9daaf689b6b888fErik break; 1418259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1419259b8f9a21fffd3858218581e9daaf689b6b888fErik CharSequence msg = b.toString(); 1420259b8f9a21fffd3858218581e9daaf689b6b888fErik event.getText().add(msg); 1421259b8f9a21fffd3858218581e9daaf689b6b888fErik event.setAddedCount(msg.length()); 1422259b8f9a21fffd3858218581e9daaf689b6b888fErik return true; 1423259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1424259b8f9a21fffd3858218581e9daaf689b6b888fErik 1425259b8f9a21fffd3858218581e9daaf689b6b888fErik /** 1426259b8f9a21fffd3858218581e9daaf689b6b888fErik * @param b 1427259b8f9a21fffd3858218581e9daaf689b6b888fErik * @param calEvent 1428259b8f9a21fffd3858218581e9daaf689b6b888fErik */ 1429259b8f9a21fffd3858218581e9daaf689b6b888fErik private void appendEventAccessibilityString(StringBuilder b, Event calEvent) { 1430259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(calEvent.getTitleAndLocation()); 1431259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(PERIOD_SPACE); 1432259b8f9a21fffd3858218581e9daaf689b6b888fErik String when; 1433259b8f9a21fffd3858218581e9daaf689b6b888fErik int flags = DateUtils.FORMAT_SHOW_DATE; 1434259b8f9a21fffd3858218581e9daaf689b6b888fErik if (calEvent.allDay) { 1435259b8f9a21fffd3858218581e9daaf689b6b888fErik flags |= DateUtils.FORMAT_UTC | DateUtils.FORMAT_SHOW_WEEKDAY; 1436259b8f9a21fffd3858218581e9daaf689b6b888fErik } else { 1437259b8f9a21fffd3858218581e9daaf689b6b888fErik flags |= DateUtils.FORMAT_SHOW_TIME; 1438259b8f9a21fffd3858218581e9daaf689b6b888fErik if (DateFormat.is24HourFormat(mContext)) { 1439259b8f9a21fffd3858218581e9daaf689b6b888fErik flags |= DateUtils.FORMAT_24HOUR; 1440259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1441259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1442259b8f9a21fffd3858218581e9daaf689b6b888fErik when = Utils.formatDateRange(mContext, calEvent.startMillis, calEvent.endMillis, flags); 1443259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(when); 1444259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(PERIOD_SPACE); 1445259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1446259b8f9a21fffd3858218581e9daaf689b6b888fErik 14476d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private class GotoBroadcaster implements Animation.AnimationListener { 14486d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private final int mCounter; 14496d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private final Time mStart; 14506d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private final Time mEnd; 14516d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 14526d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public GotoBroadcaster(Time start, Time end) { 14536d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan mCounter = ++sCounter; 14546d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan mStart = start; 14556d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan mEnd = end; 14566d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 14576d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 14586d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan @Override 14596d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public void onAnimationEnd(Animation animation) { 14606d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (mCounter == sCounter) { 1461f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mController.sendEvent(this, EventType.GO_TO, mStart, mEnd, null, -1, 1462f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan ViewType.CURRENT, CalendarController.EXTRA_GOTO_DATE, null, null); 14636d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 14646d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 14656d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 14666d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan @Override 14676d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public void onAnimationRepeat(Animation animation) { 14686d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 14696d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 14706d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan @Override 14716d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public void onAnimationStart(Animation animation) { 14726d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 14736d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 14746d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 1475ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private View switchViews(boolean forward, float xOffSet, float width) { 1476030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "switchViews(" + forward + ")..."); 1477ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float progress = Math.abs(xOffSet) / width; 1478ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (progress > 1.0f) { 1479ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan progress = 1.0f; 1480ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1481ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1482ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float inFromXValue, inToXValue; 1483ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float outFromXValue, outToXValue; 1484ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (forward) { 1485ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inFromXValue = 1.0f - progress; 1486ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inToXValue = 0.0f; 1487ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outFromXValue = -progress; 1488ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outToXValue = -1.0f; 1489ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } else { 1490ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inFromXValue = progress - 1.0f; 1491ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inToXValue = 0.0f; 1492ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outFromXValue = progress; 1493ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outToXValue = 1.0f; 1494ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1495ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 14966d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan final Time start = new Time(mBaseDate.timezone); 14976d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan start.set(mController.getTime()); 14986d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (forward) { 14996d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan start.monthDay += mNumDays; 15006d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } else { 15016d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan start.monthDay -= mNumDays; 15026d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 1503f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mController.setTime(start.normalize(true)); 1504f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan 1505f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Time newSelected = start; 15066d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 15076d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (mNumDays == 7) { 1508f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan newSelected = new Time(start); 15096d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan adjustToBeginningOfWeek(start); 15106d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 15116d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 15126d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan final Time end = new Time(start); 15136d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan end.monthDay += mNumDays - 1; 15146d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 1515ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // We have to allocate these animation objects each time we switch views 1516ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // because that is the only way to set the animation parameters. 1517ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan TranslateAnimation inAnimation = new TranslateAnimation( 1518ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, inFromXValue, 1519ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, inToXValue, 1520ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f, 1521ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f); 1522ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1523ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan TranslateAnimation outAnimation = new TranslateAnimation( 1524ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, outFromXValue, 1525ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, outToXValue, 1526ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f, 1527ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f); 1528ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1529ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // Reduce the animation duration based on how far we have already swiped. 1530ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan long duration = (long) (ANIMATION_DURATION * (1.0f - progress)); 1531ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inAnimation.setDuration(duration); 1532ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outAnimation.setDuration(duration); 15336d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan outAnimation.setAnimationListener(new GotoBroadcaster(start, end)); 1534ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.setInAnimation(inAnimation); 1535ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.setOutAnimation(outAnimation); 1536ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1537d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getCurrentView(); 1538ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.cleanup(); 1539ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.showNext(); 1540d190418220467c02327dd9b3ae1eae238889720bMichael Chan view = (DayView) mViewSwitcher.getCurrentView(); 1541f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan view.setSelected(newSelected, true); 1542ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.requestFocus(); 1543ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.reloadEvents(); 1544eaafa2b48be7194a61754604ae37b3d62e9118d8Erik view.updateTitle(); 1545e98dd73c67205b01f5348271d9a7a630003ecf52David Brown 1546ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return view; 1547ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1548ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is called after scrolling stops to move the selected hour 1550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // to the visible part of the screen. 1551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void resetSelectedHour() { 1552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < mFirstHour + 1) { 1553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + 1; 1554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionHour > mFirstHour + mNumHours - 3) { 1558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + mNumHours - 3; 1559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void initFirstHour() { 1566d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mFirstHour = mSelectionHour - mNumHours / 5; 1567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 0) { 1568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = 0; 1569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mFirstHour + mNumHours > 24) { 1570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = 24 - mNumHours; 1571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Recomputes the first full hour that is visible on screen after the 1576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * screen is scrolled. 1577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeFirstHour() { 1579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the first full hour that is visible on screen 1580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = (mViewStartY + mCellHeight + HOUR_GAP - 1) / (mCellHeight + HOUR_GAP); 1581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = mFirstHour * (mCellHeight + HOUR_GAP) - mViewStartY; 1582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void adjustHourSelection() { 1585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < 0) { 1586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = 0; 1587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mMaxAllDayEvents > 0) { 1588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = true; 1590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour > 23) { 1594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = 23; 1595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1596146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the selected hour is at least 2 time slots from the top and 1598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // bottom of the screen, then don't scroll the view. 1599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < mFirstHour + 1) { 1600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there are all-days events for the selected day but there 1601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // are no more normal events earlier in the day, then jump to 1602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the all-day event area. 1603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Exception 1: allow the user to scroll to 8am with the trackball 1604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // before jumping to the all-day event area. 1605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Exception 2: if 12am is on screen, then allow the user to select 1606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // 12am before going up to the all-day event area. 1607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 1608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mMaxAllDayEvents > 0 && mEarliestStartHour[daynum] > mSelectionHour 1609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && mFirstHour > 0 && mFirstHour < 8) { 1610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = true; 1612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + 1; 1613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour > 0) { 1617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour -= 1; 1618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY -= (mCellHeight + HOUR_GAP); 1619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 1620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 1621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour > mFirstHour + mNumHours - 3) { 1627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 24 - mNumHours) { 1628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour += 1; 1629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY += (mCellHeight + HOUR_GAP); 1630c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik if (mViewStartY > mMaxViewStartY) { 1631c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mViewStartY = mMaxViewStartY; 1632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mFirstHour == 24 - mNumHours && mFirstHourOffset > 0) { 1635c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mViewStartY = mMaxViewStartY; 1636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1640146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project void clearCachedEvents() { 1641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastReloadMillis = 0; 1642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1643146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1644146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Runnable mCancelCallback = new Runnable() { 1645146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 1646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project clearCachedEvents(); 1647146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1648146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 1649146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 165046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa /* package */ void reloadEvents() { 1651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against this being called before this view has been 1652146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // initialized. 1653ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// if (mContext == null) { 1654ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// return; 1655ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// } 1656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1657731f1cb808b7586b93615b408ab2636081fab0dcErik // Make sure our time zones are up to date 1658731f1cb808b7586b93615b408ab2636081fab0dcErik mTZUpdater.run(); 1659731f1cb808b7586b93615b408ab2636081fab0dcErik 1660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1661146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1662146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The start date is the beginning of the week at 12am 1665731f1cb808b7586b93615b408ab2636081fab0dcErik Time weekStart = new Time(Utils.getTimeZone(mContext, mTZUpdater)); 1666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.set(mBaseDate); 1667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.hour = 0; 1668146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.minute = 0; 1669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.second = 0; 1670146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = weekStart.normalize(true /* ignore isDst */); 1671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1672146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Avoid reloading events unnecessarily. 1673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (millis == mLastReloadMillis) { 1674146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1675146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1676146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastReloadMillis = millis; 1677146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1678146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // load events in the background 1679ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.startProgressSpinner(); 1680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final ArrayList<Event> events = new ArrayList<Event>(); 1681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventLoader.loadEventsInBackground(mNumDays, events, millis, new Runnable() { 1682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 1683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEvents = events; 168408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mAllDayEvents == null) { 168508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents = new ArrayList<Event>(); 168608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 168708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents.clear(); 168808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 168908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 169008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Create a shorter array for all day events 169146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan for (Event e : events) { 1692d031419da7900dab91ac9f512374d7e59bb74dceErik if (e.drawAsAllDay()) { 169308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents.add(e); 169408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 169508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 169608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 169708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // New events, new layouts 169808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mLayouts == null || mLayouts.length < events.size()) { 169908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mLayouts = new StaticLayout[events.size()]; 170008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 170108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Arrays.fill(mLayouts, null); 17023e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 170308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 170408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mAllDayLayouts == null || mAllDayLayouts.length < mAllDayEvents.size()) { 170508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayLayouts = new StaticLayout[events.size()]; 170608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 170708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Arrays.fill(mAllDayLayouts, null); 170808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 170908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 1710146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = true; 1711146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1712146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 1713ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.stopProgressSpinner(); 1714146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1715146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1716146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }, mCancelCallback); 1717146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1718146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1719146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1720146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected void onDraw(Canvas canvas) { 1721146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mRemeasure) { 1722146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project remeasure(getWidth(), getHeight()); 1723146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = false; 1724146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1725c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.save(); 1726146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1727c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik float yTranslate = -mViewStartY + DAY_HEADER_HEIGHT + mAllDayHeight; 1728c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // offset canvas by the current drag and header position 1729c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(-mViewStartX, yTranslate); 1730c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // clip to everything below the allDay area 1731c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik Rect dest = mDestRect; 1732c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.top = (int) (mFirstCell - yTranslate); 1733c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.bottom = (int) (mViewHeight - yTranslate); 1734c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.left = 0; 1735c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.right = mViewWidth; 1736c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.save(); 1737c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.clipRect(dest); 1738c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Draw the movable part of the view 1739c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik doDraw(canvas); 1740c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // restore to having no clip 1741c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.restore(); 1742146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1743146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 1744c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik float xTranslate; 1745146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartX > 0) { 1746c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik xTranslate = mViewWidth; 1747146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1748c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik xTranslate = -mViewWidth; 1749146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1750c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Move the canvas around to prep it for the next view 1751c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // specifically, shift it by a screen and undo the 1752c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // yTranslation which will be redone in the nextView's onDraw(). 1753c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(xTranslate, -yTranslate); 1754d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView nextView = (DayView) mViewSwitcher.getNextView(); 1755146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1756146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Prevent infinite recursive calls to onDraw(). 1757146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project nextView.mTouchMode = TOUCH_MODE_INITIAL_STATE; 1758146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1759146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project nextView.onDraw(canvas); 1760c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Move it back for this view 1761c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(-xTranslate, 0); 1762c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik } else { 1763c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // If we drew another view we already translated it back 1764c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // If we didn't draw another view we should be at the edge of the 1765c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // screen 1766c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(mViewStartX, -yTranslate); 1767146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1768146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1769146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the fixed areas (that don't scroll) directly to the canvas. 1770146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAfterScroll(canvas); 17718307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik if (mComputeSelectedEvents && mUpdateToast) { 17728307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik updateEventDetails(); 17738307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik mUpdateToast = false; 17748307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik } 1775146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = false; 1776146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.restore(); 1777146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1778146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1779146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAfterScroll(Canvas canvas) { 1780146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mPaint; 1781146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r = mRect; 1782146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1783146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mMaxAllDayEvents != 0) { 17841ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan drawAllDayEvents(mFirstJulianDay, mNumDays, canvas, p); 17858f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan drawUpperLeftCorner(r, canvas, p); 1786146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1787146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1788c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik drawScrollLine(r, canvas, p); 1789c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik 17903eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan drawDayHeaderLoop(r, canvas, p); 1791146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1792146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the AM and PM indicators if we're in 12 hour mode 1793146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!mIs24HourFormat) { 1794146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAmPm(canvas, p); 1795146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1796146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1797146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 179846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // This isn't really the upper-left corner. It's the square area just 1799146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // below the upper-left corner, above the hours and to the left of the 1800146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // all-day area. 18018f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private void drawUpperLeftCorner(Rect r, Canvas canvas, Paint p) { 18028f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan setupHourTextPaint(p); 18038f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawText(mAllDayString, HOURS_LEFT_MARGIN, DAY_HEADER_HEIGHT + HOURS_TOP_MARGIN 18048f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan + HOUR_GAP + mHoursTextHeight, p); 18058f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan } 1806146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1807c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik private void drawScrollLine(Rect r, Canvas canvas, Paint p) { 18088f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan final int right = mHoursWidth + (mCellWidth + DAY_GAP) * mNumDays; 18098f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan final int y = mFirstCell - 1; 18108f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan 1811c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(false); 18128f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setStyle(Style.FILL); 18138f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan 18148f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setColor(mCalendarGridLineHorizontalColor); 18158f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setStrokeWidth(GRID_LINE_WIDTH); 18168f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawLine(GRID_LINE_LEFT_MARGIN, y, right, y, p); 18171ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 18188f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setColor(mCalendarGridLineInnerHorizontalColor); 18198f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 18208f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawLine(GRID_LINE_LEFT_MARGIN, y, right, y, p); 1821c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(true); 1822c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik } 1823c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik 1824146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawDayHeaderLoop(Rect r, Canvas canvas, Paint p) { 1825146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the horizontal day background banner 18263eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarDateBannerBackground); 18273eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = 0; 18283eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = DAY_HEADER_HEIGHT; 18293eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = 0; 18303eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mHoursWidth + mNumDays * (mCellWidth + DAY_GAP); 18313eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 18323eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // 1833146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the extra space on the right side with the default background 18343eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = r.right; 18353eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mViewWidth; 18363eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 18373eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 18393eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int todayNum = mTodayJulianDay - mFirstJulianDay; 18403eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mNumDays > 1) { 18413eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.top = 0; 18423eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.bottom = DAY_HEADER_HEIGHT; 18433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 18443eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Highlight today 18453eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mFirstJulianDay <= mTodayJulianDay 18463eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan && mTodayJulianDay < (mFirstJulianDay + mNumDays)) { 18478f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan r.left = mHoursWidth + todayNum * (mCellWidth + DAY_GAP) - DAY_GAP; 18483eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.right = r.left + mCellWidth; 18493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable.setBounds(r); 18503eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable.draw(canvas); 18513eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 18523eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 18533eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw a highlight on the selected day (if any), but only if we are 18543eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // displaying more than one day. 185511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // 185611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // int selectedDayNum = mSelectionDay - mFirstJulianDay; 185711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // if (mSelectionMode != SELECTION_HIDDEN && selectedDayNum >= 0 185811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // && selectedDayNum < mNumDays) { 185911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // p.setColor(mCalendarDateSelected); 186011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // r.left = mHoursWidth + selectedDayNum * (mCellWidth + DAY_GAP); 186111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // r.right = r.left + mCellWidth; 186211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // canvas.drawRect(r, p); 186311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // } 1864146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1865146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 18663eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTypeface(mBold); 18673eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextAlign(Paint.Align.RIGHT); 1868146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaX = mCellWidth + DAY_GAP; 1869146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cell = mFirstJulianDay; 18709dd340d393575ba9740ef259e62ee7a17fc76ed1Michael Chan float x = mHoursWidth; 18719dd340d393575ba9740ef259e62ee7a17fc76ed1Michael Chan if (mNumDays == 1) { 18729dd340d393575ba9740ef259e62ee7a17fc76ed1Michael Chan x = HOURS_LEFT_MARGIN; 18739dd340d393575ba9740ef259e62ee7a17fc76ed1Michael Chan } 1874146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1875146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] dayNames; 1876146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mDateStrWidth < mCellWidth) { 1877146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dayNames = mDayStrs; 1878146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1879146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dayNames = mDayStrs2Letter; 1880146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1881146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1882d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setAntiAlias(true); 1883146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++, cell++) { 18841f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan int dayOfWeek = day + mFirstVisibleDayOfWeek; 18851f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan if (dayOfWeek >= 14) { 18861f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan dayOfWeek -= 14; 1887487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 1888487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 18893eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int color = mCalendarDateBannerTextColor; 1890071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (mNumDays == 1) { 1891071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (dayOfWeek == Time.SATURDAY) { 1892071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_saturdayColor; 1893071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else if (dayOfWeek == Time.SUNDAY) { 1894071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_sundayColor; 1895071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } 1896071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else { 1897071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa final int column = day % 7; 1898071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (Utils.isSaturday(column, mFirstDayOfWeek)) { 1899071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_saturdayColor; 1900071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else if (Utils.isSunday(column, mFirstDayOfWeek)) { 1901071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_sundayColor; 1902071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } 19033eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 19043eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 19053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan color &= 0x00FFFFFF; 19063eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (todayNum == day) { 1907f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan color |= DATE_HEADER_TODAY_ALPHA; 1908487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } else { 1909f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan color |= DATE_HEADER_ALPHA; 1910487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 1911487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 19123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(color); 1913487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan drawDayHeader(dayNames[dayOfWeek], day, cell, x, canvas, p); 1914146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project x += deltaX; 1915146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 19163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTypeface(null); 1917146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1918146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1919146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAmPm(Canvas canvas, Paint p) { 1920d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarAmPmLabel); 1921146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(AMPM_FONT_SIZE); 1922146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 1923146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 19248f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mPaint.setTextAlign(Paint.Align.LEFT); 1925146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String text = mAmString; 1926146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour >= 12) { 1927146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = mPmString; 1928146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1929146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = mFirstCell + mFirstHourOffset + 2 * mHoursTextHeight + HOUR_GAP; 19308f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawText(text, HOURS_LEFT_MARGIN, y, p); 1931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1932146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 12 && mFirstHour + mNumHours > 12) { 1933146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also draw the "PM" 1934146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = mPmString; 1935146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y = mFirstCell + mFirstHourOffset + (12 - mFirstHour) * (mCellHeight + HOUR_GAP) 1936146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project + 2 * mHoursTextHeight + HOUR_GAP; 19378f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawText(text, HOURS_LEFT_MARGIN, y, p); 1938146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1939146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1940146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1941f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan private void drawCurrentTimeLine(Rect r, final int left, final int top, Canvas canvas, 1942f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan Paint p) { 19433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.left = left - CURRENT_TIME_LINE_SIDE_BUFFER; 19441ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = left + mCellWidth + DAY_GAP + CURRENT_TIME_LINE_SIDE_BUFFER; 19453eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 19463eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.top = top - mCurrentTimeLine.getIntrinsicHeight() / 2; 19473eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.bottom = r.top + mCurrentTimeLine.getIntrinsicHeight(); 1948bd0e834aea317236d574f8738fe11a51fdc87968Erik 19493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine.setBounds(r); 19503eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine.draw(canvas); 1951bd0e834aea317236d574f8738fe11a51fdc87968Erik } 1952bd0e834aea317236d574f8738fe11a51fdc87968Erik 1953146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void doDraw(Canvas canvas) { 1954146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mPaint; 1955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r = mRect; 1956146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1957146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawGridBackground(r, canvas, p); 1958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawHours(r, canvas, p); 1959146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1960146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw each day 1961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int x = mHoursWidth; 1962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaX = mCellWidth + DAY_GAP; 1963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cell = mFirstJulianDay; 1964146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++, cell++) { 196508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // TODO Wow, this needs cleanup. drawEvents loop through all the 196608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // events on every call. 1967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawEvents(cell, x, HOUR_GAP, canvas, p); 196846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // If this is today 196946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (cell == mTodayJulianDay) { 19701ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int lineY = mCurrentTime.hour * (mCellHeight + HOUR_GAP) 19711ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan + ((mCurrentTime.minute * mCellHeight) / 60) + 1; 19721ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 197346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // And the current time shows up somewhere on the screen 197446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (lineY >= mViewStartY && lineY < mViewStartY + mViewHeight - 2) { 1975bd0e834aea317236d574f8738fe11a51fdc87968Erik drawCurrentTimeLine(r, x, lineY, canvas, p); 1976bd0e834aea317236d574f8738fe11a51fdc87968Erik } 1977bd0e834aea317236d574f8738fe11a51fdc87968Erik } 1978146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project x += deltaX; 1979146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1980146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1981146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1982146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawHours(Rect r, Canvas canvas, Paint p) { 19833eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Comment out as the background will be a drawable 19843eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 1985146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the background for the hour labels 19863eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarHourBackground); 19873eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = 0; 19883eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = 24 * (mCellHeight + HOUR_GAP) + HOUR_GAP; 19893eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = 0; 19903eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mHoursWidth; 19913eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1992146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the bottom left corner with the default grid background 19943eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = r.bottom; 19953eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = mBitmapHeight; 19963eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 19973eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1998146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw a highlight on the selected hour (if needed) 2000ba902466b19b11d587468e354edc58e542707747Michael Chan if (mSelectionMode != SELECTION_HIDDEN && !mSelectionAllDay) { 2001ba902466b19b11d587468e354edc58e542707747Michael Chan // p.setColor(mCalendarHourSelected); 20023937a47bc5a1afb9701e1d0565fae31f5800590dErik int daynum = mSelectionDay - mFirstJulianDay; 2003ba902466b19b11d587468e354edc58e542707747Michael Chan r.top = mSelectionHour * (mCellHeight + HOUR_GAP); 20041ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top + mCellHeight + HOUR_GAP; 200546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan r.left = mHoursWidth + daynum * (mCellWidth + DAY_GAP) + DAY_GAP; 20063937a47bc5a1afb9701e1d0565fae31f5800590dErik r.right = r.left + mCellWidth + DAY_GAP; 2007ba902466b19b11d587468e354edc58e542707747Michael Chan 2008ba902466b19b11d587468e354edc58e542707747Michael Chan // Draw a border around the highlighted grid hour. 20091ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // drawEmptyRect(canvas, r, mSelectionPaint.getColor()); 2010ba902466b19b11d587468e354edc58e542707747Michael Chan saveSelectionPosition(r.left, r.top, r.right, r.bottom); 20113937a47bc5a1afb9701e1d0565fae31f5800590dErik 20123937a47bc5a1afb9701e1d0565fae31f5800590dErik // Also draw the highlight on the grid 20133937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setColor(mCalendarGridAreaSelected); 20143937a47bc5a1afb9701e1d0565fae31f5800590dErik r.top += HOUR_GAP; 20153937a47bc5a1afb9701e1d0565fae31f5800590dErik r.right -= DAY_GAP; 20163937a47bc5a1afb9701e1d0565fae31f5800590dErik canvas.drawRect(r, p); 2017ba902466b19b11d587468e354edc58e542707747Michael Chan } 2018146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20198f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan setupHourTextPaint(p); 2020146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20218f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan int y = HOUR_GAP + mHoursTextHeight + HOURS_TOP_MARGIN; 2022146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2023146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < 24; i++) { 2024146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String time = mHourStrs[i]; 20258f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawText(time, HOURS_LEFT_MARGIN, y, p); 2026146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += mCellHeight + HOUR_GAP; 2027146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2028146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2029146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20308f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private void setupHourTextPaint(Paint p) { 20318f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setColor(mCalendarHourLabelColor); 20328f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setTextSize(HOURS_FONT_SIZE); 2033f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(Typeface.DEFAULT); 20348f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setTextAlign(Paint.Align.LEFT); 20358f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setAntiAlias(true); 20368f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan } 20378f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan 20383eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private void drawDayHeader(String dayStr, int day, int cell, float x, Canvas canvas, Paint p) { 2039487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int dateNum = mFirstVisibleDate + day; 2040146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (dateNum > mMonthLength) { 2041146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dateNum -= mMonthLength; 2042146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2043146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20443eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 20453eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan String dateNumStr = String.valueOf(dateNum); 20463eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mNumDays > 1) { 20473eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float y = DAY_HEADER_HEIGHT - DAY_HEADER_BOTTOM_MARGIN; 20483eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 20493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 20503eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += mCellWidth - DAY_HEADER_RIGHT_MARGIN; 20513eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 2052f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(mBold); 20533eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dateNumStr, x, y, p); 20543eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 20553eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the week 20563eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x -= p.measureText(dateNumStr) + DAY_HEADER_LEFT_MARGIN; 2057f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setColor((p.getColor() & 0x00FFFFFF) | DAY_HEADER_ALPHA); 20583eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 2059f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(Typeface.DEFAULT); 20603eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dayStr, x, y, p); 2061146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 20623eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float y = DAY_HEADER_HEIGHT - DAY_HEADER_ONE_DAY_BOTTOM_MARGIN; 206311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setTextAlign(Paint.Align.LEFT); 2064146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2065f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan int dateColor = p.getColor(); 2066f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan 20673eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the week 20683eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += DAY_HEADER_ONE_DAY_LEFT_MARGIN; 2069f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setColor((dateColor & 0x00FFFFFF) | DAY_HEADER_ALPHA); 20703eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 2071f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(Typeface.DEFAULT); 20723eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dayStr, x, y, p); 2073d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan 20743eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 20753eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += p.measureText(dayStr) + DAY_HEADER_ONE_DAY_RIGHT_MARGIN; 2076f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setColor(dateColor); 20773eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 2078f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(mBold); 20793eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dateNumStr, x, y, p); 2080d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan } 2081146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2082146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2083146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawGridBackground(Rect r, Canvas canvas, Paint p) { 2084146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint.Style savedStyle = p.getStyle(); 2085146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20863eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the outer horizontal grid lines 2087d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarGridLineHorizontalColor); 20889c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan p.setStyle(Style.FILL); 20893937a47bc5a1afb9701e1d0565fae31f5800590dErik 2090146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 20913eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopX = mHoursWidth + (mCellWidth + DAY_GAP) * mNumDays; 2092000ba1109e2f4e527e9227fe341598ceeb3fbca6Michael Chan float y = 0; 20933eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaY = mCellHeight + HOUR_GAP; 20943937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setStrokeWidth(GRID_LINE_WIDTH); 209502041687c35441e8a21cb763f1fc3a26525292efDavid Brown int linesIndex = 0; 2096146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int hour = 0; hour <= 24; hour++) { 20978f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mLines[linesIndex++] = GRID_LINE_LEFT_MARGIN; 209802041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 209902041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopX; 210002041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 2101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += deltaY; 2102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 210302041687c35441e8a21cb763f1fc3a26525292efDavid Brown if (mCalendarGridLineVerticalColor != mCalendarGridLineHorizontalColor) { 210402041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 210502041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 210602041687c35441e8a21cb763f1fc3a26525292efDavid Brown p.setColor(mCalendarGridLineVerticalColor); 210702041687c35441e8a21cb763f1fc3a26525292efDavid Brown } 2108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 21093eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the outer vertical grid lines 21103eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startY = 0; 21113eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP); 21123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaX = mCellWidth + DAY_GAP; 21131ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan float x = mHoursWidth; 2114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++) { 21151ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x += deltaX; 211602041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 211702041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 211802041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 211902041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 2120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 212102041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 2122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 21233eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner horizontal grid lines 21243eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerHorizontalColor); 21253eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 21263eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan y = 0; 212702041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 21283eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int hour = 0; hour <= 24; hour++) { 21298f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mLines[linesIndex++] = GRID_LINE_LEFT_MARGIN; 213002041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 213102041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopX; 213202041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 21333eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan y += deltaY; 21343eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 213502041687c35441e8a21cb763f1fc3a26525292efDavid Brown if (mCalendarGridLineInnerVerticalColor != mCalendarGridLineInnerHorizontalColor) { 213602041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 213702041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 213802041687c35441e8a21cb763f1fc3a26525292efDavid Brown p.setColor(mCalendarGridLineInnerVerticalColor); 213902041687c35441e8a21cb763f1fc3a26525292efDavid Brown } 21403eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 21413eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner vertical grid lines 21421ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x = mHoursWidth; 21433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int day = 0; day < mNumDays; day++) { 21441ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x += deltaX; 214502041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 214602041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 214702041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 214802041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 21493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 215002041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 21513eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 2152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Restore the saved style. 2153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setStyle(savedStyle); 2154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 2155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event getSelectedEvent() { 2158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 2159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // There is no event at the selected hour, so create a new event. 2160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return getNewEvent(mSelectionDay, getSelectedTimeInMillis(), 2161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getSelectedMinutesSinceMidnight()); 2162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return mSelectedEvent; 2164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean isEventSelected() { 2167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return (mSelectedEvent != null); 2168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event getNewEvent() { 2171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return getNewEvent(mSelectionDay, getSelectedTimeInMillis(), 2172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getSelectedMinutesSinceMidnight()); 2173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project static Event getNewEvent(int julianDay, long utcMillis, 2176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int minutesSinceMidnight) { 2177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = Event.newInstance(); 2178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startDay = julianDay; 2179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endDay = julianDay; 2180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startMillis = utcMillis; 2181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endMillis = event.startMillis + MILLIS_PER_HOUR; 2182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startTime = minutesSinceMidnight; 2183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endTime = event.startTime + MINUTES_PER_HOUR; 2184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return event; 2185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int computeMaxStringWidth(int currentMax, String[] strings, Paint p) { 2188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float maxWidthF = 0.0f; 2189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = strings.length; 2191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < len; i++) { 2192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float width = p.measureText(strings[i]); 2193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxWidthF = Math.max(width, maxWidthF); 2194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxWidth = (int) (maxWidthF + 0.5); 2196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxWidth < currentMax) { 2197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxWidth = currentMax; 2198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return maxWidth; 2200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void saveSelectionPosition(float left, float top, float right, float bottom) { 2203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.left = (int) left; 2204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.right = (int) right; 2205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.top = (int) top; 2206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.bottom = (int) bottom; 2207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect getCurrentSelectionPosition() { 2210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect box = new Rect(); 2211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.top = mSelectionHour * (mCellHeight + HOUR_GAP); 2212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.bottom = box.top + mCellHeight + HOUR_GAP; 2213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 2214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.left = mHoursWidth + daynum * (mCellWidth + DAY_GAP); 2215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.right = box.left + mCellWidth + DAY_GAP; 2216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return box; 2217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 22191ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void setupTextRect(Rect r) { 22201ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom <= r.top || r.right <= r.left) { 22211ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top; 22221ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = r.left; 222336a4668f603c432d08ad156cd7c731f9838c0212Michael Chan return; 222436a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 222536a4668f603c432d08ad156cd7c731f9838c0212Michael Chan 22261ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom - r.top > EVENT_TEXT_TOP_MARGIN + EVENT_TEXT_BOTTOM_MARGIN) { 22271ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top += EVENT_TEXT_TOP_MARGIN; 22281ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom -= EVENT_TEXT_BOTTOM_MARGIN; 222936a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 22301ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.right - r.left > EVENT_TEXT_LEFT_MARGIN + EVENT_TEXT_RIGHT_MARGIN) { 22311ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left += EVENT_TEXT_LEFT_MARGIN; 22321ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right -= EVENT_TEXT_RIGHT_MARGIN; 223336a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 22349c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan } 22359c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan 22361ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void setupAllDayTextRect(Rect r) { 22371ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom <= r.top || r.right <= r.left) { 22381ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top; 22391ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = r.left; 224036a4668f603c432d08ad156cd7c731f9838c0212Michael Chan return; 224136a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 224236a4668f603c432d08ad156cd7c731f9838c0212Michael Chan 22431ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom - r.top > EVENT_ALL_DAY_TEXT_TOP_MARGIN + EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN) { 22441ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top += EVENT_ALL_DAY_TEXT_TOP_MARGIN; 22451ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom -= EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN; 224636a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 22471ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.right - r.left > EVENT_ALL_DAY_TEXT_LEFT_MARGIN + EVENT_ALL_DAY_TEXT_RIGHT_MARGIN) { 22481ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left += EVENT_ALL_DAY_TEXT_LEFT_MARGIN; 22491ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right -= EVENT_ALL_DAY_TEXT_RIGHT_MARGIN; 225036a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 22519c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan } 22529c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan 22533e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh /** 22543e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh * Return the layout for a numbered event. Create it if not already existing 22553e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh */ 225608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout getEventLayout(StaticLayout[] layouts, int i, Event event, Paint paint, 225708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Rect r) { 225808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (i < 0 || i >= layouts.length) { 22590a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan return null; 22600a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan } 22610a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan 226208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = layouts[i]; 2263f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan // Check if we have already initialized the StaticLayout and that 2264f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan // the width hasn't changed (due to vertical resizing which causes 2265f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan // re-layout of events at min height) 22661ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (layout == null || r.width() != layout.getWidth()) { 2267f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan String text = drawTextSanitizer(event.getTitleAndLocation(), MAX_EVENT_TEXT_LEN); 22683e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 2269f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan if (event.selfAttendeeStatus == Attendees.ATTENDEE_STATUS_DECLINED) { 2270f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan paint.setColor(mDeclinedEventTextColor); 2271f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan } else { 2272f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan paint.setColor(mEventTextColor); 2273f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan } 2274f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan 22753e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh // Leave a one pixel boundary on the left and right of the rectangle for the event 22761ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan layout = new StaticLayout(text, 0, text.length(), new TextPaint(paint), r.width(), 22771ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true, null, r.width()); 22783e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 227908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan layouts[i] = layout; 22803e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 22813e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 22823e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh return layout; 22833e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 22843e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 22851ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void drawAllDayEvents(int firstDay, int numDays, Canvas canvas, Paint p) { 22861ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (mSelectionAllDay) { 22871ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // Draw the highlight on the selected all-day area 22881ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mRect.top = DAY_HEADER_HEIGHT + 1; 22891ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mRect.bottom = mRect.top + mAllDayHeight + ALLDAY_TOP_MARGIN - 2; 22901ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int daynum = mSelectionDay - mFirstJulianDay; 22911ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mRect.left = mHoursWidth + daynum * (mCellWidth + DAY_GAP); 22921ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mRect.right = mRect.left + mCellWidth + DAY_GAP - 1; 22931ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setColor(mCalendarGridAreaSelected); 22941ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawRect(mRect, p); 22953e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 22963e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 2297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(NORMAL_FONT_SIZE); 2298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextAlign(Paint.Align.LEFT); 2299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint eventTextPaint = mEventTextPaint; 2300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the background for the all-day events area 23023eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = DAY_HEADER_HEIGHT; 23033eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = r.top + mAllDayHeight + ALLDAY_TOP_MARGIN; 23043eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = mHoursWidth; 23053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = r.left + mNumDays * (mCellWidth + DAY_GAP); 23063eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarAllDayBackground); 23073eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 2308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the extra space on the right side with the default background 23103eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = r.right; 23113eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mViewWidth; 23123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 23133eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 2314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 23153eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the outer vertical grid lines 2316d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarGridLineVerticalColor); 23179c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan p.setStyle(Style.FILL); 23183eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_WIDTH); 2319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 23203eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startY = DAY_HEADER_HEIGHT; 23213eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopY = startY + mAllDayHeight + ALLDAY_TOP_MARGIN; 23223eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaX = mCellWidth + DAY_GAP; 23231ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan float x = mHoursWidth; 232402041687c35441e8a21cb763f1fc3a26525292efDavid Brown int linesIndex = 0; 23251ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // Line bounding the top of the all day area 23268f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mLines[linesIndex++] = GRID_LINE_LEFT_MARGIN; 23271ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 23281ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = mHoursWidth + deltaX * mNumDays; 23291ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 23301ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 23313eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int day = 0; day < mNumDays; day++) { 23321ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x += deltaX; 233302041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 233402041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 233502041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 233602041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 2337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 233802041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 23393eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 23403eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner vertical grid lines 23413eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerVerticalColor); 23421ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x = mHoursWidth; 23433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 234402041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 23451ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // Line bounding the top of the all day area 23468f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mLines[linesIndex++] = GRID_LINE_LEFT_MARGIN; 23471ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 23481ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = mHoursWidth + (deltaX) * mNumDays; 23491ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 23501ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 23513eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int day = 0; day < mNumDays; day++) { 23521ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x += deltaX; 235302041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 235402041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 235502041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 235602041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 23573eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 235802041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 23593eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 2360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 2361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setStyle(Style.FILL); 2362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 23633eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int y = DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 2364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float left = mHoursWidth; 2365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int lastDay = firstDay + numDays - 1; 236608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final ArrayList<Event> events = mAllDayEvents; 2367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 2368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float drawHeight = mAllDayHeight; 2369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float numRectangles = mMaxAllDayEvents; 2370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 2371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 2372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startDay = event.startDay; 2373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endDay = event.endDay; 2374c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (startDay > lastDay || endDay < firstDay) { 2375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2376c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2377c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (startDay < firstDay) { 2378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startDay = firstDay; 2379c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2380c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (endDay > lastDay) { 2381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endDay = lastDay; 2382c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startIndex = startDay - firstDay; 2384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endIndex = endDay - firstDay; 2385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float height = drawHeight / numRectangles; 2386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Prevent a single event from getting too big 2388f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan if (height > MAX_HEIGHT_OF_ONE_ALLDAY_EVENT) { 2389f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan height = MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 2390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Leave a one-pixel space between the vertical day lines and the 2393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event rectangle. 23949c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan event.left = left + startIndex * (mCellWidth + DAY_GAP); 23959c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan event.right = left + endIndex * (mCellWidth + DAY_GAP) + mCellWidth; 2396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.top = y + height * event.getColumn(); 23979c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan event.bottom = event.top + height; 2398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 23991ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Rect r = drawEventRect(event, canvas, p, eventTextPaint); 24001ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan setupAllDayTextRect(r); 240108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = getEventLayout(mAllDayLayouts, i, event, eventTextPaint, r); 240208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan drawEventText(layout, r, canvas, r.top, r.bottom); 2403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check if this all-day event intersects the selected day 2405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay && mComputeSelectedEvents) { 2406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (startDay <= mSelectionDay && endDay >= mSelectionDay) { 2407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 2408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay) { 2413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the neighbors for the list of all-day events that 2414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // intersect the selected day. 2415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeAllDayNeighbors(); 2416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Set the selection position to zero so that when we move down 2418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // to the normal event area, we will highlight the topmost event. 2419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project saveSelectionPosition(0f, 0f, 0f, 0f); 2420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeAllDayNeighbors() { 2424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 2425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len == 0 || mSelectedEvent != null) { 2426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear all the links 2430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = null; 2433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = null; 2434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = null; 2435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = null; 2436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2438146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each event in the selected event list "mSelectedEvents", find 243946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // its neighbors in the up and down directions. This could be done 2440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // more efficiently by sorting on the Event.getColumn() field, but 2441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the list is expected to be very small. 2442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Find the event in the same row as the previously selected all-day 2444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event, if any. 2445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startPosition = -1; 2446d031419da7900dab91ac9f512374d7e59bb74dceErik if (mPrevSelectedEvent != null && mPrevSelectedEvent.drawAsAllDay()) { 2447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startPosition = mPrevSelectedEvent.getColumn(); 2448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxPosition = -1; 2450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event startEvent = null; 2451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event maxPositionEvent = null; 2452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2453146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int position = ev.getColumn(); 2455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (position == startPosition) { 2456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEvent = ev; 2457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (position > maxPosition) { 2458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxPositionEvent = ev; 2459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxPosition = position; 2460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int jj = 0; jj < len; jj++) { 2462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (jj == ii) { 2463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event neighbor = mSelectedEvents.get(jj); 2466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborPosition = neighbor.getColumn(); 2467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborPosition == position - 1) { 2468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = neighbor; 2469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborPosition == position + 1) { 2470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = neighbor; 2471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (startEvent != null) { 2475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = startEvent; 2476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = maxPositionEvent; 2478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawEvents(int date, int left, int top, Canvas canvas, Paint p) { 2482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint eventTextPaint = mEventTextPaint; 2483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellWidth = mCellWidth; 2484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellHeight = mCellHeight; 2485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use the selected hour as the selection region 2487259b8f9a21fffd3858218581e9daaf689b6b888fErik Rect selectionArea = mSelectionRect; 2488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.top = top + mSelectionHour * (cellHeight + HOUR_GAP); 2489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.bottom = selectionArea.top + cellHeight; 2490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.left = left; 2491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.right = selectionArea.left + cellWidth; 2492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 249308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final ArrayList<Event> events = mEvents; 2494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 2495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project EventGeometry geometry = mEventGeometry; 2496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 249708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final int viewEndY = mViewStartY + mViewHeight - DAY_HEADER_HEIGHT - mAllDayHeight; 2498146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 2499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 2500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!geometry.computeEventRect(date, left, top, cellWidth, event)) { 2501146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2503146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 250408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Don't draw it if it is not visible 250508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (event.bottom < mViewStartY || event.top > viewEndY) { 250608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan continue; 250708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 250808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 2509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (date == mSelectionDay && !mSelectionAllDay && mComputeSelectedEvents 2510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && geometry.eventIntersectsSelection(event, selectionArea)) { 2511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 2512146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2513146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 25141ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Rect r = drawEventRect(event, canvas, p, eventTextPaint); 25151ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan setupTextRect(r); 251608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 251708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Don't draw text if it is not visible 251808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (r.top > viewEndY || r.bottom < mViewStartY) { 251908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan continue; 252008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 252108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = getEventLayout(mLayouts, i, event, eventTextPaint, r); 252208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // TODO: not sure why we are 4 pixels off 252346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan drawEventText(layout, r, canvas, mViewStartY + 4, mViewStartY + mViewHeight 252446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan - DAY_HEADER_HEIGHT - mAllDayHeight); 2525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2527259b8f9a21fffd3858218581e9daaf689b6b888fErik 2528259b8f9a21fffd3858218581e9daaf689b6b888fErik if (mComputeSelectedEvents) { 2529259b8f9a21fffd3858218581e9daaf689b6b888fErik mDispatchAccessibilityEventRunnable.mEventType = mSelectedEvent == null ? 2530259b8f9a21fffd3858218581e9daaf689b6b888fErik AccessibilityEvent.TYPE_VIEW_SELECTED : 2531259b8f9a21fffd3858218581e9daaf689b6b888fErik AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED; 2532259b8f9a21fffd3858218581e9daaf689b6b888fErik post(mDispatchAccessibilityEventRunnable); 2533259b8f9a21fffd3858218581e9daaf689b6b888fErik } 2534259b8f9a21fffd3858218581e9daaf689b6b888fErik 2535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (date == mSelectionDay && !mSelectionAllDay && isFocused() 2536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && mSelectionMode != SELECTION_HIDDEN) { 2537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeNeighbors(); 2538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Computes the "nearest" neighbor event in four directions (left, right, 2542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // up, down) for each of the events in the mSelectedEvents array. 2543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeNeighbors() { 2544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 2545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len == 0 || mSelectedEvent != null) { 2546146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear all the links 2550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = null; 2553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = null; 2554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = null; 2555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = null; 2556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event startEvent = mSelectedEvents.get(0); 255946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int startEventDistance1 = 100000; // any large number 256046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int startEventDistance2 = 100000; // any large number 2561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevLocation = FROM_NONE; 2562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevTop; 2563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevBottom; 2564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevLeft; 2565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevRight; 2566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevCenter = 0; 2567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect box = getCurrentSelectionPosition(); 2568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPrevSelectedEvent != null) { 2569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = (int) mPrevSelectedEvent.top; 2570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = (int) mPrevSelectedEvent.bottom; 2571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = (int) mPrevSelectedEvent.left; 2572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = (int) mPrevSelectedEvent.right; 2573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check if the previously selected event intersects the previous 257446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // selection box. (The previously selected event may be from a 2575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // much older selection box.) 2576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevTop >= mPrevBox.bottom || prevBottom <= mPrevBox.top 2577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || prevRight <= mPrevBox.left || prevLeft >= mPrevBox.right) { 2578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 2579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 2580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 2581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = mPrevBox.left; 2582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = mPrevBox.right; 2583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Clip the top and bottom to the previous selection box. 2585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevTop < mPrevBox.top) { 2586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 2587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevBottom > mPrevBox.bottom) { 2589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 2590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Just use the previously drawn selection box 2594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 2595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 2596146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = mPrevBox.left; 2597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = mPrevBox.right; 2598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out where we came from and compute the center of that area. 2601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevLeft >= box.right) { 2602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was to the right of us. 2603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_RIGHT; 2604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevTop + prevBottom) / 2; 2605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevRight <= box.left) { 2606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was to the left of us. 2607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_LEFT; 2608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevTop + prevBottom) / 2; 2609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevBottom <= box.top) { 2610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was above us. 2611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_ABOVE; 2612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevLeft + prevRight) / 2; 2613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevTop >= box.bottom) { 2614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was below us. 2615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_BELOW; 2616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevLeft + prevRight) / 2; 2617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each event in the selected event list "mSelectedEvents", search 2620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // all the other events in that list for the nearest neighbor in 4 2621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // directions. 2622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startTime = ev.startTime; 2626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endTime = ev.endTime; 2627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int left = (int) ev.left; 2628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int right = (int) ev.right; 2629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int top = (int) ev.top; 2630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (top < box.top) { 2631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project top = box.top; 2632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int bottom = (int) ev.bottom; 2634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom > box.bottom) { 2635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project bottom = box.bottom; 2636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (false) { 2638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL 2639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 2640ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (DateFormat.is24HourFormat(mContext)) { 2641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags |= DateUtils.FORMAT_24HOUR; 2642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 264346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan String timeRange = DateUtils.formatDateRange(mContext, ev.startMillis, 264446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan ev.endMillis, flags); 264546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan Log.i("Cal", "left: " + left + " right: " + right + " top: " + top + " bottom: " 264646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan + bottom + " ev: " + timeRange + " " + ev.title); 264746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 264846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int upDistanceMin = 10000; // any large number 264946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int downDistanceMin = 10000; // any large number 265046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int leftDistanceMin = 10000; // any large number 265146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int rightDistanceMin = 10000; // any large number 2652146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event upEvent = null; 2653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event downEvent = null; 2654146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event leftEvent = null; 2655146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event rightEvent = null; 2656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the starting event closest to the previously selected event, 265846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // if any. distance1 takes precedence over distance2. 2659146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance1 = 0; 2660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance2 = 0; 2661146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevLocation == FROM_ABOVE) { 2662146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (left >= prevCenter) { 2663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = left - prevCenter; 2664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (right <= prevCenter) { 2665146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - right; 2666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = top - prevBottom; 2668146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_BELOW) { 2669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (left >= prevCenter) { 2670146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = left - prevCenter; 2671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (right <= prevCenter) { 2672146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - right; 2673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2674146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = prevTop - bottom; 2675146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_LEFT) { 2676146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom <= prevCenter) { 2677146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - bottom; 2678146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (top >= prevCenter) { 2679146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = top - prevCenter; 2680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = left - prevRight; 2682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_RIGHT) { 2683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom <= prevCenter) { 2684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - bottom; 2685146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (top >= prevCenter) { 2686146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = top - prevCenter; 2687146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2688146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = prevLeft - right; 2689146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2690146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance1 < startEventDistance1 2691146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || (distance1 == startEventDistance1 && distance2 < startEventDistance2)) { 2692146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEvent = ev; 2693146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEventDistance1 = distance1; 2694146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEventDistance2 = distance2; 2695146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2696146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2697146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each neighbor, figure out if it is above or below or left 2698146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // or right of me and compute the distance. 2699146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int jj = 0; jj < len; jj++) { 2700146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (jj == ii) { 2701146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2702146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2703146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event neighbor = mSelectedEvents.get(jj); 2704146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborLeft = (int) neighbor.left; 2705146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborRight = (int) neighbor.right; 2706146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighbor.endTime <= startTime) { 2707146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely above me. 2708146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we overlap the same column, then compute the distance. 2709146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft < right && neighborRight > left) { 2710146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = startTime - neighbor.endTime; 2711146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < upDistanceMin) { 2712146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upDistanceMin = distance; 2713146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upEvent = neighbor; 2714146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == upDistanceMin) { 2715146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (left + right) / 2; 2716146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = 0; 2717146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentLeft = (int) upEvent.left; 2718146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentRight = (int) upEvent.right; 2719146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (currentRight <= center) { 2720146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = center - currentRight; 2721146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (currentLeft >= center) { 2722146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = currentLeft - center; 2723146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2724146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2725146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = 0; 2726146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborRight <= center) { 2727146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = center - neighborRight; 2728146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborLeft >= center) { 2729146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = neighborLeft - center; 2730146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2731146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2732146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upDistanceMin = distance; 2733146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upEvent = neighbor; 2734146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2735146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2736146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2737146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighbor.startTime >= endTime) { 2738146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely below me. 2739146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we overlap the same column, then compute the distance. 2740146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft < right && neighborRight > left) { 2741146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = neighbor.startTime - endTime; 2742146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < downDistanceMin) { 2743146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downDistanceMin = distance; 2744146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downEvent = neighbor; 2745146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == downDistanceMin) { 2746146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (left + right) / 2; 2747146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = 0; 2748146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentLeft = (int) downEvent.left; 2749146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentRight = (int) downEvent.right; 2750146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (currentRight <= center) { 2751146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = center - currentRight; 2752146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (currentLeft >= center) { 2753146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = currentLeft - center; 2754146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2755146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2756146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = 0; 2757146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborRight <= center) { 2758146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = center - neighborRight; 2759146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborLeft >= center) { 2760146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = neighborLeft - center; 2761146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2762146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2763146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downDistanceMin = distance; 2764146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downEvent = neighbor; 2765146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2766146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2767146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2768146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2769146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2770146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft >= right) { 2771146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely to the right of me. 2772146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Take the closest neighbor in the y direction. 2773146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (top + bottom) / 2; 2774146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = 0; 2775146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborBottom = (int) neighbor.bottom; 2776146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborTop = (int) neighbor.top; 2777146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborBottom <= center) { 2778146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = center - neighborBottom; 2779146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborTop >= center) { 2780146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = neighborTop - center; 2781146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2782146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < rightDistanceMin) { 2783146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightDistanceMin = distance; 2784146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightEvent = neighbor; 2785146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == rightDistanceMin) { 2786146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the closest in the x direction 2787146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = neighborLeft - right; 2788146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = (int) rightEvent.left - right; 2789146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2790146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightDistanceMin = distance; 2791146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightEvent = neighbor; 2792146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2793146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2794146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborRight <= left) { 2795146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely to the left of me. 2796146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Take the closest neighbor in the y direction. 2797146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (top + bottom) / 2; 2798146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = 0; 2799146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborBottom = (int) neighbor.bottom; 2800146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborTop = (int) neighbor.top; 2801146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborBottom <= center) { 2802146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = center - neighborBottom; 2803146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborTop >= center) { 2804146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = neighborTop - center; 2805146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2806146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < leftDistanceMin) { 2807146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftDistanceMin = distance; 2808146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftEvent = neighbor; 2809146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == leftDistanceMin) { 2810146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the closest in the x direction 2811146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = left - neighborRight; 2812146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = left - (int) leftEvent.right; 2813146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2814146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftDistanceMin = distance; 2815146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftEvent = neighbor; 2816146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2817146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2818146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2819146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = upEvent; 2821146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = downEvent; 2822146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = leftEvent; 2823146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = rightEvent; 2824146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2825146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = startEvent; 2826146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2827146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 28281ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private Rect drawEventRect(Event event, Canvas canvas, Paint p, Paint eventTextPaint) { 282911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw the Event Rect 28301ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Rect r = mRect; 28311ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top = (int) event.top + EVENT_RECT_TOP_MARGIN; 28321ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = (int) event.bottom - EVENT_RECT_BOTTOM_MARGIN; 28331ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = (int) event.left + EVENT_RECT_LEFT_MARGIN; 28341ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = (int) event.right - EVENT_RECT_RIGHT_MARGIN; 28351ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 2836f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan Drawable eventBoxDrawable; 2837f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan switch (event.selfAttendeeStatus) { 2838f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_INVITED: 2839f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_DECLINED: 2840f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan eventBoxDrawable = mUnconfirmedOrDeclinedEventBoxDrawable; 2841f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan break; 2842f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_NONE: // Your own events 2843f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_ACCEPTED: 2844f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_TENTATIVE: 2845f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan default: 2846f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan eventBoxDrawable = mAcceptedOrTentativeEventBoxDrawable; 2847f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan break; 2848f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan } 2849f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan eventBoxDrawable.setBounds(r); 2850f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan eventBoxDrawable.draw(canvas); 2851146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 28521ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setStyle(Style.FILL); 2853e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 2854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If this event is selected, then use the selection color 2855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == event) { 28561ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan boolean paintIt = false; 28571ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int color = 0; 2858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_PRESSED) { 2859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 2860146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 2861146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // box = mBoxPressed; 286278f58c119af15ed85a727e16cddd793ced4c809dMichael Chan color = mPressedColor; 28631ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan paintIt = true; 2864146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionMode == SELECTION_SELECTED) { 2865146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 2866146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 2867146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // box = mBoxSelected; 286878f58c119af15ed85a727e16cddd793ced4c809dMichael Chan color = mPressedColor; 28691ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan paintIt = true; 2870146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionMode == SELECTION_LONGPRESS) { 2871146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // box = mBoxLongPressed; 287278f58c119af15ed85a727e16cddd793ced4c809dMichael Chan color = mPressedColor; 28731ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan paintIt = true; 28741ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan } 28751ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 28761ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (paintIt) { 28771ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setColor(color); 28781ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawRect(r, p); 2879146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2880146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2881146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 288211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw cal color square border 28831ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top = (int) event.top + CALENDAR_COLOR_SQUARE_V_OFFSET; 28841ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = (int) event.left + CALENDAR_COLOR_SQUARE_H_OFFSET; 28851ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top + CALENDAR_COLOR_SQUARE_SIZE + 1; 28861ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = r.left + CALENDAR_COLOR_SQUARE_SIZE + 1; 288711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setColor(0xFFFFFFFF); 28881ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawRect(r, p); 28898af2529989a9b10a0bb84736695c22fc02a17a4aThe Android Open Source Project 289011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw cal color 28911ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top++; 28921ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left++; 28931ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom--; 28941ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right--; 289511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setColor(event.color); 28961ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawRect(r, p); 2897e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 28983eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Setup rect for drawEventText which follows 28991ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top = (int) event.top + EVENT_RECT_TOP_MARGIN; 29001ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = (int) event.bottom - EVENT_RECT_BOTTOM_MARGIN; 29011ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = (int) event.left + EVENT_RECT_LEFT_MARGIN; 29021ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = (int) event.right - EVENT_RECT_RIGHT_MARGIN; 29031ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan return r; 2904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2905146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 29060d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan private Pattern drawTextSanitizerFilter = Pattern.compile("[\t\n],"); 29070d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 29080d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // Sanitize a string before passing it to drawText or else we get little 29090d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // squares. For newlines and tabs before a comma, delete the character. 29100d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // Otherwise, just replace them with a space. 2911f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan private String drawTextSanitizer(String string, int maxEventTextLen) { 29120d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan Matcher m = drawTextSanitizerFilter.matcher(string); 2913f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan string = m.replaceAll(","); 2914f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan 2915f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan int len = string.length(); 2916f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan if (len > maxEventTextLen) { 2917f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan string = string.substring(0, maxEventTextLen); 2918f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan len = maxEventTextLen; 2919f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan } 2920f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan 2921f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan return string.replace('\n', ' '); 29220d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan } 29230d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 292408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private void drawEventText(StaticLayout eventLayout, Rect rect, Canvas canvas, int top, 292508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan int bottom) { 29261ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // drawEmptyRect(canvas, rect, 0xFFFF00FF); // for debugging 29271ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 29281ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int width = rect.right - rect.left; 29291ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int height = rect.bottom - rect.top; 2930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the rectangle is too small for text, then return 29320a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan if (eventLayout == null || width < MIN_CELL_WIDTH_FOR_TEXT) { 2933f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan return; 2934f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 2935f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan 293608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan int totalLineHeight = 0; 2937f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan int lineCount = eventLayout.getLineCount(); 2938f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan for (int i = 0; i < lineCount; i++) { 2939f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan int lineBottom = eventLayout.getLineBottom(i); 2940f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan if (lineBottom <= height) { 294108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan totalLineHeight = lineBottom; 294208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 294308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan break; 2944f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 2945f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 2946f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan 294708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (totalLineHeight == 0 || rect.top > bottom || rect.top + totalLineHeight < top) { 2948146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2949146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 29513e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh // Use a StaticLayout to format the string. 29523e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh canvas.save(); 29531ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.translate(rect.left, rect.top); 29541ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.left = 0; 29551ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.right = width; 29561ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.top = 0; 295708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan rect.bottom = totalLineHeight; 295808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 295908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // There's a bug somewhere. If this rect is outside of a previous 296008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // cliprect, this becomes a no-op. What happens is that the text draw 296108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // past the event rect. The current fix is to not draw the staticLayout 296208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // at all if it is completely out of bound. 29631ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.clipRect(rect); 29643e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh eventLayout.draw(canvas); 29653e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh canvas.restore(); 2966146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 29681ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // This is to replace p.setStyle(Style.STROKE); canvas.drawRect() since it 29691ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // doesn't work well with hardware acceleration 29701ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void drawEmptyRect(Canvas canvas, Rect r, int color) { 29711ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int linesIndex = 0; 29721ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.left; 29731ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.top; 29741ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.right; 29751ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.top; 29761ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 29771ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.left; 29781ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.bottom; 29791ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.right; 29801ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.bottom; 29811ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 29821ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.left; 29831ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.top; 29841ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.left; 29851ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.bottom; 29861ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 29871ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.right; 29881ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.top; 29891ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.right; 29901ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.bottom; 29911ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mPaint.setColor(color); 29921ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawLines(mLines, 0, linesIndex, mPaint); 29931ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan } 29941ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 2995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void updateEventDetails() { 2996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null || mSelectionMode == SELECTION_HIDDEN 2997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || mSelectionMode == SELECTION_LONGPRESS) { 2998146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 2999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3000146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3001666fc5e8ddbac15c951aad738bd818ee307eae42Erik if (mLastPopupEventID == mSelectedEvent.id) { 3002666fc5e8ddbac15c951aad738bd818ee307eae42Erik return; 3003666fc5e8ddbac15c951aad738bd818ee307eae42Erik } 3004666fc5e8ddbac15c951aad738bd818ee307eae42Erik 3005666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = mSelectedEvent.id; 3006146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3007146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Remove any outstanding callbacks to dismiss the popup. 3008146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getHandler().removeCallbacks(mDismissPopup); 3009146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3010146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = mSelectedEvent; 3011146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView titleView = (TextView) mPopupView.findViewById(R.id.event_title); 3012146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project titleView.setText(event.title); 3013146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3014146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ImageView imageView = (ImageView) mPopupView.findViewById(R.id.reminder_icon); 3015146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView.setVisibility(event.hasAlarm ? View.VISIBLE : View.GONE); 3016146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3017146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView = (ImageView) mPopupView.findViewById(R.id.repeat_icon); 3018146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView.setVisibility(event.isRepeating ? View.VISIBLE : View.GONE); 3019146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3020146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags; 3021146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.allDay) { 302246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan flags = DateUtils.FORMAT_UTC | DateUtils.FORMAT_SHOW_DATE 302346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_ALL; 3024146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3025146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE 3026146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_ALL 3027146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 3028146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3029ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (DateFormat.is24HourFormat(mContext)) { 3030146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags |= DateUtils.FORMAT_24HOUR; 3031146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 303246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan String timeRange = Utils.formatDateRange(mContext, event.startMillis, event.endMillis, 303346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan flags); 3034146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView timeView = (TextView) mPopupView.findViewById(R.id.time); 3035146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project timeView.setText(timeRange); 3036146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3037146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView whereView = (TextView) mPopupView.findViewById(R.id.where); 3038146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final boolean empty = TextUtils.isEmpty(event.location); 3039146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project whereView.setVisibility(empty ? View.GONE : View.VISIBLE); 3040146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!empty) whereView.setText(event.location); 3041146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3042146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.showAtLocation(this, Gravity.BOTTOM | Gravity.LEFT, mHoursWidth, 5); 3043146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project postDelayed(mDismissPopup, POPUP_DISMISS_DELAY); 3044146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3045146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3046146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The following routines are called from the parent activity when certain 3047146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // touch events occur. 30484484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doDown(MotionEvent ev) { 3049146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_DOWN; 3050146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = 0; 3051146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mOnFlingCalled = false; 3052146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getHandler().removeCallbacks(mContinueScroll); 3053146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 30554484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doSingleTapUp(MotionEvent ev) { 3056d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (!mHandleActionUp) { 3057d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return; 3058d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3059d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3060146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int x = (int) ev.getX(); 3061146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = (int) ev.getY(); 3062146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectedDay = mSelectionDay; 3063146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectedHour = mSelectionHour; 3064146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3065146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean validPosition = setSelectionFromPosition(x, y); 3066146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!validPosition) { 3067360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan if (y < DAY_HEADER_HEIGHT) { 3068360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan Time selectedTime = new Time(mBaseDate); 3069360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan selectedTime.setJulianDay(mSelectionDay); 3070360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan selectedTime.hour = mSelectionHour; 3071360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan selectedTime.normalize(true /* ignore isDst */); 3072360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan mController.sendEvent(this, EventType.GO_TO, null, null, selectedTime, -1, 3073360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan ViewType.DAY, CalendarController.EXTRA_GOTO_DATE, null, null); 3074360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan } 3075146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3076146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 307880bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan mSelectionMode = SELECTION_SELECTED; 3079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3080146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 308180bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan if (mSelectedEvent != null) { 308280bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan // If the tap is on an event, launch the "View event" view 3083344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, mSelectedEvent.id, 3084344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mSelectedEvent.startMillis, mSelectedEvent.endMillis, (int) ev.getRawX(), 308587f993ff96172f508d3f241f8a425f953c7eb739RoboErik (int) ev.getRawY(), getSelectedTimeInMillis()); 3086344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan } else if (selectedDay == mSelectionDay && selectedHour == mSelectionHour) { 3087344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan // If the tap is on an already selected hour slot, then create a new 3088344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan // event 3089344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 309087f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis(), 0, (int) ev.getRawX(), (int) ev.getRawY(), -1); 3091344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan } else { 3092344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan Time startTime = new Time(mBaseDate); 3093344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.setJulianDay(mSelectionDay); 3094344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.hour = mSelectionHour; 3095344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.normalize(true /* ignore isDst */); 309683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 309783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time endTime = new Time(startTime); 309883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan endTime.hour++; 309983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 310046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mController.sendEvent(this, EventType.GO_TO, startTime, endTime, -1, ViewType.CURRENT, 310146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan CalendarController.EXTRA_GOTO_TIME, null, null); 3102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 31054484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doLongPress(MotionEvent ev) { 3106d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // Scale gesture in progress 3107d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mStartingSpanY != 0) { 3108d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return; 3109d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3110d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 311180bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan int x = (int) ev.getX(); 311280bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan int y = (int) ev.getY(); 311380bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan 311480bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan boolean validPosition = setSelectionFromPosition(x, y); 311580bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan if (!validPosition) { 311680bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan // return if the touch wasn't on an area of concern 311780bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan return; 311880bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan } 311980bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan 3120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 3121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project performLongClick(); 3123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 31254484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doScroll(MotionEvent e1, MotionEvent e2, float deltaX, float deltaY) { 31266d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (isAnimating()) { 31276d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan return; 31286d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 31296d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 3130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use the distance from the current point to the initial touch instead 3131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // of deltaX and deltaY to avoid accumulating floating-point rounding 313246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // errors. Also, we don't need floats, we can use ints. 3133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceX = (int) e1.getX() - (int) e2.getX(); 3134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceY = (int) e1.getY() - (int) e2.getY(); 3135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we haven't figured out the predominant scroll direction yet, 3137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // then do it now. 3138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mTouchMode == TOUCH_MODE_DOWN) { 3139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int absDistanceX = Math.abs(distanceX); 3140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int absDistanceY = Math.abs(distanceY); 3141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrollStartY = mViewStartY; 3142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPreviousDirection = 0; 3143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the x distance is at least twice the y distance, then lock 314546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // the scroll horizontally. Otherwise scroll vertically. 3146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (absDistanceX >= 2 * absDistanceY) { 3147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_HSCROLL; 3148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = distanceX; 3149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initNextView(-mViewStartX); 3150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_VSCROLL; 3152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 3154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We are already scrolling horizontally, so check if we 3155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // changed the direction of scrolling so that the other week 3156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // is now visible. 3157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = distanceX; 3158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distanceX != 0) { 3159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int direction = (distanceX > 0) ? 1 : -1; 3160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (direction != mPreviousDirection) { 3161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The user has switched the direction of scrolling 3162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // so re-init the next view 3163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initNextView(-mViewStartX); 3164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPreviousDirection = direction; 3165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_VSCROLL) != 0) { 3170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mScrollStartY + distanceY; 3171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 3172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 3173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mViewStartY > mMaxViewStartY) { 3174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mMaxViewStartY; 3175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeFirstHour(); 3177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = true; 3180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3181d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan mSelectionMode = SELECTION_HIDDEN; 3182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 31856d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private boolean isAnimating() { 31866d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan Animation in = mViewSwitcher.getInAnimation(); 31876d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (in != null && in.hasStarted() && !in.hasEnded()) { 31886d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan return true; 31896d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 31906d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan Animation out = mViewSwitcher.getOutAnimation(); 31916d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (out != null && out.hasStarted() && !out.hasEnded()) { 31926d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan return true; 31936d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 31946d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan return false; 31956d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 31966d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 31974484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 31986d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (isAnimating()) { 31996d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan return; 32006d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 32016d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 3202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_INITIAL_STATE; 3203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_HIDDEN; 3204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mOnFlingCalled = true; 3205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaX = (int) e2.getX() - (int) e1.getX(); 3206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceX = Math.abs(deltaX); 3207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaY = (int) e2.getY() - (int) e1.getY(); 3208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceY = Math.abs(deltaY); 32096d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (DEBUG) Log.d(TAG, "doFling: deltaX " + deltaX 3210d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan + ", HORIZONTAL_FLING_THRESHOLD " + HORIZONTAL_FLING_THRESHOLD); 3211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3212d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan if ((distanceX >= HORIZONTAL_FLING_THRESHOLD) && (distanceX > distanceY)) { 3213030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown // Horizontal fling. 321411638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // initNextView(deltaX); 3215d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan switchViews(deltaX < 0, mViewStartX, mViewWidth); 3216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = 0; 3217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3220030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown // Vertical fling. 3221030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown mViewStartX = 0; 3222030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown 3223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Continue scrolling vertically 3224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mContinueScroll.init((int) velocityY / 20); 3225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project post(mContinueScroll); 3226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean initNextView(int deltaX) { 3229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Change the view to the previous day or week 3230d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getNextView(); 3231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time date = view.mBaseDate; 3232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.set(mBaseDate); 3233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean switchForward; 3234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (deltaX > 0) { 3235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay -= mNumDays; 3236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = mSelectionDay - mNumDays; 3237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchForward = false; 3238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay += mNumDays; 3240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = mSelectionDay + mNumDays; 3241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchForward = true; 3242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.normalize(true /* ignore isDst */); 3244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initView(view); 3245ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan view.layout(getLeft(), getTop(), getRight(), getBottom()); 3246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.reloadEvents(); 3247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return switchForward; 3248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3250d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 3251d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public boolean onScaleBegin(ScaleGestureDetector detector) { 3252d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = false; 3253d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float gestureCenterInPixels = detector.getFocusY() - DAY_HEADER_HEIGHT - mAllDayHeight; 3254d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) / (mCellHeight + DAY_GAP); 3255d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3256d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = Math.max(MIN_Y_SPAN, Math.abs(detector.getCurrentSpanY())); 3257d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = mCellHeight; 3258d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3259d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 3260d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float ViewStartHour = mViewStartY / (float) (mCellHeight + DAY_GAP); 3261d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.d(TAG, "mGestureCenterHour:" + mGestureCenterHour + "\tViewStartHour: " 3262d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + ViewStartHour + "\tmViewStartY:" + mViewStartY + "\tmCellHeight:" 3263d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + mCellHeight); 3264d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3265d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3266d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 3267d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3268d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3269d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 3270d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public boolean onScale(ScaleGestureDetector detector) { 3271d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float spanY = Math.abs(detector.getCurrentSpanY()); 3272d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3273d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = (int) (mCellHeightBeforeScaleGesture * spanY / mStartingSpanY); 3274d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3275d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight < mMinCellHeight) { 3276d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // If mStartingSpanY is too small, even a small increase in the 3277d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // gesture can bump the mCellHeight beyond MAX_CELL_HEIGHT 3278d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = Math.max(MIN_Y_SPAN, spanY); 3279d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = mMinCellHeight; 3280d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = mMinCellHeight; 3281d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } else if (mCellHeight > MAX_CELL_HEIGHT) { 3282d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = spanY; 3283d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = MAX_CELL_HEIGHT; 3284d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = MAX_CELL_HEIGHT; 3285d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3286d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3287d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan int gestureCenterInPixels = (int) detector.getFocusY() - DAY_HEADER_HEIGHT - mAllDayHeight; 3288d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = (int) (mGestureCenterHour * (mCellHeight + DAY_GAP)) - gestureCenterInPixels; 3289d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mMaxViewStartY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP) - mGridAreaHeight; 3290d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3291d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 3292d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float ViewStartHour = mViewStartY / (float) (mCellHeight + DAY_GAP); 3293d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.d(TAG, " mGestureCenterHour:" + mGestureCenterHour + "\tViewStartHour: " 3294d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + ViewStartHour + "\tmViewStartY:" + mViewStartY + "\tmCellHeight:" 3295d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + mCellHeight + " SpanY:" + detector.getCurrentSpanY()); 3296d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3297d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3298d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mViewStartY < 0) { 3299d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = 0; 3300d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) 3301d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan / (float) (mCellHeight + DAY_GAP); 3302d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } else if (mViewStartY > mMaxViewStartY) { 3303d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = mMaxViewStartY; 3304d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) 3305d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan / (float) (mCellHeight + DAY_GAP); 3306d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3307d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan computeFirstHour(); 3308d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3309d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mRemeasure = true; 3310d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan invalidate(); 3311d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 3312d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3313d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3314d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 3315d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public void onScaleEnd(ScaleGestureDetector detector) { 3316d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = 0; 3317d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3318d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 3320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onTouchEvent(MotionEvent ev) { 3321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int action = ev.getAction(); 3322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 33231ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan if ((mTouchMode & TOUCH_MODE_HSCROLL) == 0) { 33241ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan mScaleGestureDetector.onTouchEvent(ev); 33251ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan if (mScaleGestureDetector.isInProgress()) { 33261ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan return true; 33271ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan } 3328d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3329d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (action) { 333146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_DOWN: 333246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.e(TAG, "ACTION_DOWN"); 3333d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = true; 333446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 3335d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 333646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 333746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_MOVE: 333846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.e(TAG, "ACTION_MOVE"); 333946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 3340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 334146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 334246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_UP: 334346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.e(TAG, "ACTION_UP " + mHandleActionUp); 334446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 334546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (!mHandleActionUp) { 334646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mHandleActionUp = true; 33477abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project return true; 334846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 334946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mOnFlingCalled) { 335046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 335146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 335246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 335346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mTouchMode = TOUCH_MODE_INITIAL_STATE; 335446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (Math.abs(mViewStartX) > mHorizontalSnapBackThreshold) { 335546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // The user has gone beyond the threshold so switch views 335646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.d(TAG, "- horizontal scroll: switch views"); 335746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan switchViews(mViewStartX > 0, mViewStartX, mViewWidth); 335846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mViewStartX = 0; 335946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 336046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 336146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Not beyond the threshold so invalidate which will cause 336246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // the view to snap back. Also call recalc() to ensure 336346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // that we have the correct starting date and title. 336446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.d(TAG, "- horizontal scroll: snap back"); 336546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan recalc(); 336646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan invalidate(); 336746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mViewStartX = 0; 336846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 336946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 337046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 337146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // If we were scrolling, then reset the selected hour so that it 337246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // is visible. 337346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mScrolling) { 337446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = false; 337546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan resetSelectedHour(); 3376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 337846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 3379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 338046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // This case isn't expected to happen. 338146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_CANCEL: 338246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.e(TAG, "ACTION_CANCEL"); 338346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 3384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 3385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project resetSelectedHour(); 3386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 338746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 338846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan default: 338946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.e(TAG, "Not MotionEvent"); 339046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mGestureDetector.onTouchEvent(ev)) { 339146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 339246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 339346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return super.onTouchEvent(ev); 3394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { 3398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project MenuItem item; 3399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the trackball is held down, then the context menu pops up and 340146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // we never get onKeyUp() for the long-press. So check for it here 3402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // and change the selection to the long-press state. 3403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode != SELECTION_LONGPRESS) { 3404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 3405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3408e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan final long startMillis = getSelectedTimeInMillis(); 3409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags = DateUtils.FORMAT_SHOW_TIME 3410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT 3411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_SHOW_WEEKDAY; 3412c5f92d7bdeb1950ace783cc022aa41a4b4f00cd6Erik final String title = Utils.formatDateRange(mContext, startMillis, startMillis, flags); 3413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project menu.setHeaderTitle(title); 3414e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numSelectedEvents = mSelectedEvents.size(); 3416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 1) { 3417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Day view. 3418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is a selected event, then allow it to be viewed and 3420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // edited. 3421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (numSelectedEvents >= 1) { 34224484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_VIEW, 0, R.string.event_view); 3423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_info_details); 3425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3426ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan int accessLevel = getEventAccessLevel(mContext, mSelectedEvent); 3427a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel == ACCESS_LEVEL_EDIT) { 34284484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_EDIT, 0, R.string.event_edit); 3429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_edit); 3431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('e'); 3432a505627659f6bfba8869eac8089f7030f2d0d92cErik } 3433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3434a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel >= ACCESS_LEVEL_DELETE) { 34354484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_DELETE, 0, R.string.event_delete); 3436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_delete); 3438146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 34404484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 3441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_add); 3443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('n'); 3444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Otherwise, if the user long-pressed on a blank hour, allow 344646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // them to create an event. They can also do this by tapping. 34474484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 3448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_add); 3450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('n'); 3451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3453146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Week view. 3454e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is a selected event, then allow it to be viewed and 3456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // edited. 3457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (numSelectedEvents >= 1) { 34584484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_VIEW, 0, R.string.event_view); 3459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_info_details); 3461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3462ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan int accessLevel = getEventAccessLevel(mContext, mSelectedEvent); 3463a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel == ACCESS_LEVEL_EDIT) { 34644484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_EDIT, 0, R.string.event_edit); 3465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_edit); 3467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('e'); 3468a505627659f6bfba8869eac8089f7030f2d0d92cErik } 3469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3470a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel >= ACCESS_LEVEL_DELETE) { 34714484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_DELETE, 0, R.string.event_delete); 3472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_delete); 3474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 34754484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan } 3476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 34774484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 34784484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 34794484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_add); 34804484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('n'); 3481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 34824484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_DAY, 0, R.string.show_day_view); 34834484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 34844484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_day); 34854484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('d'); 3486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private class ContextMenuHandler implements MenuItem.OnMenuItemClickListener { 3492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onMenuItemClick(MenuItem item) { 3493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (item.getItemId()) { 34944484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_VIEW: { 3495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 3496a7694eead7cbb293990bc89c3906e17bad36194cErik mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT_DETAILS, 34979e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.id, mSelectedEvent.startMillis, 349887f993ff96172f508d3f241f8a425f953c7eb739RoboErik mSelectedEvent.endMillis, 0, 0, -1); 3499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3501146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 35024484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_EDIT: { 3503146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 35049e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.EDIT_EVENT, 35059e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.id, mSelectedEvent.startMillis, 350687f993ff96172f508d3f241f8a425f953c7eb739RoboErik mSelectedEvent.endMillis, 0, 0, -1); 3507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3508146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 35104484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_DAY: { 3511487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mController.sendEvent(this, EventType.GO_TO, getSelectedTime(), null, -1, 35129e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan ViewType.DAY); 3513146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3514146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 35154484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_AGENDA: { 3516487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mController.sendEvent(this, EventType.GO_TO, getSelectedTime(), null, -1, 35179e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan ViewType.AGENDA); 3518146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3519146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 35204484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_CREATE: { 3521146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 3522146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 35239e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 352487f993ff96172f508d3f241f8a425f953c7eb739RoboErik startMillis, endMillis, 0, 0, -1); 3525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 35274484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_DELETE: { 3528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 3529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 3530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long begin = selectedEvent.startMillis; 3531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long end = selectedEvent.endMillis; 3532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long id = selectedEvent.id; 35339e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.DELETE_EVENT, id, begin, 353487f993ff96172f508d3f241f8a425f953c7eb739RoboErik end, 0, 0, -1); 3535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project default: { 3539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return false; 3540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 3543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3546a505627659f6bfba8869eac8089f7030f2d0d92cErik private static int getEventAccessLevel(Context context, Event e) { 3547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ContentResolver cr = context.getContentResolver(); 3548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int visibility = Calendars.NO_ACCESS; 3550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Get the calendar id for this event 3552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Cursor cursor = cr.query(ContentUris.withAppendedId(Events.CONTENT_URI, e.id), 3553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project new String[] { Events.CALENDAR_ID }, 3554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* selection */, 3555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* selectionArgs */, 3556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* sort */); 3557e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3558e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan if (cursor == null) { 3559a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 3560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3561e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3562e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan if (cursor.getCount() == 0) { 3563e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan cursor.close(); 3564a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 3565e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan } 3566e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.moveToFirst(); 3568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long calId = cursor.getLong(0); 3569697bd6a8cec36cc75c72603674e57e4c6fe42dbfKen Shirriff cursor.close(); 3570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Uri uri = Calendars.CONTENT_URI; 3572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String where = String.format(CALENDARS_WHERE, calId); 3573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor = cr.query(uri, CALENDARS_PROJECTION, where, null, null); 3574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 35756d34cec523930368976bc8d358d0a6de1da3462cMichael Chan String calendarOwnerAccount = null; 3576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (cursor != null) { 3577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.moveToFirst(); 3578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project visibility = cursor.getInt(CALENDARS_INDEX_ACCESS_LEVEL); 35796d34cec523930368976bc8d358d0a6de1da3462cMichael Chan calendarOwnerAccount = cursor.getString(CALENDARS_INDEX_OWNER_ACCOUNT); 3580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.close(); 3581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3582e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 35836d34cec523930368976bc8d358d0a6de1da3462cMichael Chan if (visibility < Calendars.CONTRIBUTOR_ACCESS) { 3584a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 35856d34cec523930368976bc8d358d0a6de1da3462cMichael Chan } 3586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 35876d34cec523930368976bc8d358d0a6de1da3462cMichael Chan if (e.guestsCanModify) { 3588a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_EDIT; 3589a505627659f6bfba8869eac8089f7030f2d0d92cErik } 3590a505627659f6bfba8869eac8089f7030f2d0d92cErik 359146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (!TextUtils.isEmpty(calendarOwnerAccount) 359246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan && calendarOwnerAccount.equalsIgnoreCase(e.organizer)) { 3593a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_EDIT; 3594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3596a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_DELETE; 3597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Sets mSelectionDay and mSelectionHour based on the (x,y) touch position. 3601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * If the touch position is not within the displayed grid, then this 3602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * method returns false. 3603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 3604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param x the x position of the touch 3605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param y the y position of the touch 3606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return true if the touch position is valid 3607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 3608360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan private boolean setSelectionFromPosition(int x, final int y) { 3609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (x < mHoursWidth) { 3610360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan x = mHoursWidth; 3611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int day = (x - mHoursWidth) / (mCellWidth + DAY_GAP); 3614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (day >= mNumDays) { 3615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project day = mNumDays - 1; 3616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project day += mFirstJulianDay; 3618360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan mSelectionDay = day; 3619360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan 3620360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan if (y < DAY_HEADER_HEIGHT) { 3621360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan return false; 3622360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan } 362346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 362446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectionHour = mFirstHour; /* First fully visible hour */ 362546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 362646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (y < mFirstCell) { 3627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = true; 3628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 362946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // y is now offset from top of the scrollable region 363055a26d7062d5aa1a1b001b7271bb137276ab807eErik int adjustedY = y - mFirstCell; 363146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 363255a26d7062d5aa1a1b001b7271bb137276ab807eErik if (adjustedY < mFirstHourOffset) { 363346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan --mSelectionHour; /* In the partially visible hour */ 363446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 363555a26d7062d5aa1a1b001b7271bb137276ab807eErik mSelectionHour += (adjustedY - mFirstHourOffset) / (mCellHeight + HOUR_GAP); 363646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 363746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 3638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = false; 3639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3640360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan 3641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project findSelectedEvent(x, y); 364246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 364346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// Log.i("Cal", "setSelectionFromPosition( " + x + ", " + y + " ) day: " + day + " hour: " 364446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// + mSelectionHour + " mFirstCell: " + mFirstCell + " mFirstHourOffset: " 364546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// + mFirstHourOffset); 3646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// if (mSelectedEvent != null) { 364746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// Log.i("Cal", " num events: " + mSelectedEvents.size() + " event: " 364846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// + mSelectedEvent.title); 3649146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// for (Event ev : mSelectedEvents) { 3650146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL 3651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 365246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// String timeRange = formatDateRange(mContext, ev.startMillis, ev.endMillis, flags); 3653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// 3654146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", " " + timeRange + " " + ev.title); 3655146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// } 3656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// } 3657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 3658146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3659146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void findSelectedEvent(int x, int y) { 3661146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int date = mSelectionDay; 3662146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellWidth = mCellWidth; 366308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final ArrayList<Event> events = mEvents; 3664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 3665146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int left = mHoursWidth + (mSelectionDay - mFirstJulianDay) * (cellWidth + DAY_GAP); 3666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int top = 0; 3667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 3668146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 3670146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay) { 3671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float yDistance; 367246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan float minYdistance = 10000.0f; // any large number 3673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event closestEvent = null; 3674146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float drawHeight = mAllDayHeight; 36753eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int yOffset = DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 3676146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 3677146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 3678d031419da7900dab91ac9f512374d7e59bb74dceErik if (!event.drawAsAllDay()) { 3679146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.startDay <= mSelectionDay && event.endDay >= mSelectionDay) { 3683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float numRectangles = event.getMaxColumns(); 3684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float height = drawHeight / numRectangles; 3685f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan if (height > MAX_HEIGHT_OF_ONE_ALLDAY_EVENT) { 3686f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan height = MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 3687146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3688146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float eventTop = yOffset + height * event.getColumn(); 3689146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float eventBottom = eventTop + height; 3690146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (eventTop < y && eventBottom > y) { 3691146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the touch is inside the event rectangle, then 3692146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // add the event. 3693146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 3694146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = event; 3695146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3696146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3697146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Find the closest event 3698146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (eventTop >= y) { 3699146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project yDistance = eventTop - y; 3700146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3701146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project yDistance = y - eventBottom; 3702146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3703146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (yDistance < minYdistance) { 3704146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project minYdistance = yDistance; 3705146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = event; 3706146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3707146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3708146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3709146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3710146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = closestEvent; 3711146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3712146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3713146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3714146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Adjust y for the scrollable bitmap 3715146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += mViewStartY - mFirstCell; 3716146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3717146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use a region around (x,y) for the selection region 3718146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect region = mRect; 3719146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.left = x - 10; 3720146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.right = x + 10; 3721146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.top = y - 10; 3722146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.bottom = y + 10; 3723146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3724146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project EventGeometry geometry = mEventGeometry; 3725146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3726146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 3727146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 3728146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the event rectangle. 3729146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!geometry.computeEventRect(date, left, top, cellWidth, event)) { 3730146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3731146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3732146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3733146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the event intersects the selection region, then add it to 3734146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // mSelectedEvents. 3735146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (geometry.eventIntersectsSelection(event, region)) { 3736146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 3737146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3738146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3739146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3740146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there are any events in the selected region, then assign the 3741146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // closest one to mSelectedEvent. 3742146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvents.size() > 0) { 3743146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 3744146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event closestEvent = null; 374546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan float minDist = mViewWidth + mViewHeight; // some large distance 3746146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int index = 0; index < len; index++) { 3747146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(index); 3748146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float dist = geometry.pointToEvent(x, y, ev); 3749146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (dist < minDist) { 3750146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project minDist = dist; 3751146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = ev; 3752146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3753146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3754146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = closestEvent; 3755146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3756146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Keep the selected hour and day consistent with the selected 375746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // event. They could be different if we touched on an empty hour 375846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // slot very close to an event in the previous hour slot. In 3759146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // that case we will select the nearby event. 3760146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startDay = mSelectedEvent.startDay; 3761146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endDay = mSelectedEvent.endDay; 3762146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionDay < startDay) { 3763146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = startDay; 3764146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionDay > endDay) { 3765146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = endDay; 3766146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3767146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3768146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startHour = mSelectedEvent.startTime / 60; 3769146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endHour; 3770146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent.startTime < mSelectedEvent.endTime) { 3771146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endHour = (mSelectedEvent.endTime - 1) / 60; 3772146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3773146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endHour = mSelectedEvent.endTime / 60; 3774146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3775146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3776146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < startHour) { 3777146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = startHour; 3778146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionHour > endHour) { 3779146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = endHour; 3780146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3781146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3782146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3783146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3784146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Encapsulates the code to continue the scrolling after the 378546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // finger is lifted. Instead of stopping the scroll immediately, 3786146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the scroll continues to "free spin" and gradually slows down. 3787146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private class ContinueScroll implements Runnable { 3788146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int mSignDeltaY; 3789146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int mAbsDeltaY; 3790146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float mFloatDeltaY; 3791146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long mFreeSpinTime; 3792146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final float FRICTION_COEF = 0.7F; 3793146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final long FREE_SPIN_MILLIS = 180; 3794146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int MAX_DELTA = 60; 3795146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SCROLL_REPEAT_INTERVAL = 30; 3796146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3797146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void init(int deltaY) { 3798146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSignDeltaY = 0; 3799146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (deltaY > 0) { 3800146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSignDeltaY = 1; 3801146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (deltaY < 0) { 3802146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSignDeltaY = -1; 3803146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3804146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = Math.abs(deltaY); 3805146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3806146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Limit the maximum speed 3807146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY > MAX_DELTA) { 3808146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = MAX_DELTA; 3809146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3810146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFloatDeltaY = mAbsDeltaY; 3811146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFreeSpinTime = System.currentTimeMillis() + FREE_SPIN_MILLIS; 3812146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", "init scroll: mAbsDeltaY: " + mAbsDeltaY 3813146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// + " mViewStartY: " + mViewStartY); 3814146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3815146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3816146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 3817146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long time = System.currentTimeMillis(); 3818146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3819146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Start out with a frictionless "free spin" 3820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (time > mFreeSpinTime) { 3821146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the delta is small, then apply a fixed deceleration. 3822146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Otherwise 3823146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY <= 10) { 3824146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY -= 2; 3825146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3826146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFloatDeltaY *= FRICTION_COEF; 3827146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = (int) mFloatDeltaY; 3828146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3829146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3830146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY < 0) { 3831146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = 0; 3832146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3833146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3834146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3835146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSignDeltaY == 1) { 3836146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY -= mAbsDeltaY; 3837146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY += mAbsDeltaY; 3839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", " scroll: mAbsDeltaY: " + mAbsDeltaY 3841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// + " mViewStartY: " + mViewStartY); 3842146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3843146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 3844146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 3845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = 0; 3846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mViewStartY > mMaxViewStartY) { 3847146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mMaxViewStartY; 3848146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = 0; 3849146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3850146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3851146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeFirstHour(); 3852146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3853146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY > 0) { 3854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project postDelayed(this, SCROLL_REPEAT_INTERVAL); 3855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Done scrolling. 3857146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 3858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project resetSelectedHour(); 3859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3860146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3861146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3862146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3863146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3864146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3865146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3866bd0e834aea317236d574f8738fe11a51fdc87968Erik * Cleanup the pop-up and timers. 3867146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 3868146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void cleanup() { 3869146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against null-pointer exceptions 3870146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPopup != null) { 3871146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3872146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3873666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 3874146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Handler handler = getHandler(); 3875146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (handler != null) { 3876146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project handler.removeCallbacks(mDismissPopup); 3877bd0e834aea317236d574f8738fe11a51fdc87968Erik handler.removeCallbacks(mUpdateCurrentTime); 3878146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3879e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3880d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Utils.setSharedPreference(mContext, GeneralPreferences.KEY_DEFAULT_CELL_HEIGHT, 3881d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight); 3882d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 38837abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project // Turn off redraw 38847abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project mRemeasure = false; 3885146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3886146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3887bd0e834aea317236d574f8738fe11a51fdc87968Erik /** 3888bd0e834aea317236d574f8738fe11a51fdc87968Erik * Restart the update timer 3889bd0e834aea317236d574f8738fe11a51fdc87968Erik */ 3890bd0e834aea317236d574f8738fe11a51fdc87968Erik public void restartCurrentTimeUpdates() { 3891bd0e834aea317236d574f8738fe11a51fdc87968Erik post(mUpdateCurrentTime); 3892bd0e834aea317236d574f8738fe11a51fdc87968Erik } 3893bd0e834aea317236d574f8738fe11a51fdc87968Erik 389446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 389546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan protected void onDetachedFromWindow() { 3896146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cleanup(); 3897146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project super.onDetachedFromWindow(); 3898146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3899146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3900146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project class DismissPopup implements Runnable { 3901146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 3902146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against null-pointer exceptions 3903146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPopup != null) { 3904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3905146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3906146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3907146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3908bd0e834aea317236d574f8738fe11a51fdc87968Erik 3909bd0e834aea317236d574f8738fe11a51fdc87968Erik class UpdateCurrentTime implements Runnable { 3910bd0e834aea317236d574f8738fe11a51fdc87968Erik public void run() { 3911bd0e834aea317236d574f8738fe11a51fdc87968Erik long currentTime = System.currentTimeMillis(); 3912bd0e834aea317236d574f8738fe11a51fdc87968Erik mCurrentTime.set(currentTime); 3913bd0e834aea317236d574f8738fe11a51fdc87968Erik //% causes update to occur on 5 minute marks (11:10, 11:15, 11:20, etc.) 3914bd0e834aea317236d574f8738fe11a51fdc87968Erik postDelayed(mUpdateCurrentTime, 3915bd0e834aea317236d574f8738fe11a51fdc87968Erik UPDATE_CURRENT_TIME_DELAY - (currentTime % UPDATE_CURRENT_TIME_DELAY)); 3916bd0e834aea317236d574f8738fe11a51fdc87968Erik mTodayJulianDay = Time.getJulianDay(currentTime, mCurrentTime.gmtoff); 3917bd0e834aea317236d574f8738fe11a51fdc87968Erik invalidate(); 3918bd0e834aea317236d574f8738fe11a51fdc87968Erik } 3919bd0e834aea317236d574f8738fe11a51fdc87968Erik } 3920ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3921ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener { 3922ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3923ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onSingleTapUp(MotionEvent ev) { 3924d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doSingleTapUp(ev); 3925ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3926ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3927ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3928ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3929ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public void onLongPress(MotionEvent ev) { 3930d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doLongPress(ev); 3931ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3932ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3933ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3934ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 3935d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doScroll(e1, e2, distanceX, distanceY); 3936ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3937ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3938ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3939ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3940ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 3941d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doFling(e1, e2, velocityX, velocityY); 3942ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3943ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3944ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3945ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3946ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onDown(MotionEvent ev) { 3947d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doDown(ev); 3948ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3949ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3950ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3951cd405a28e6821b116dcf3c531805d0c90b6cc08cErik 3952cd405a28e6821b116dcf3c531805d0c90b6cc08cErik @Override 3953cd405a28e6821b116dcf3c531805d0c90b6cc08cErik public boolean onLongClick(View v) { 3954cd405a28e6821b116dcf3c531805d0c90b6cc08cErik mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 395587f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis(), 0, -1, -1, -1); 3956cd405a28e6821b116dcf3c531805d0c90b6cc08cErik return true; 3957cd405a28e6821b116dcf3c531805d0c90b6cc08cErik } 3958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project} 3959