DayView.java revision d885c1a5876735bbf2c0086956101bd70bac37e7
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 22146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.ContentResolver; 23146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.ContentUris; 24146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context; 25146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.res.Resources; 26146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.res.TypedArray; 27146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.database.Cursor; 28146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Canvas; 29146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Paint; 30dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.graphics.Paint.Style; 31146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Path; 32dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.graphics.Path.Direction; 33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Rect; 34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.RectF; 35146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Typeface; 36c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawaimport android.graphics.drawable.Drawable; 37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.net.Uri; 38146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.os.Handler; 39146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.provider.Calendar.Attendees; 40146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.provider.Calendar.Calendars; 41146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.provider.Calendar.Events; 4256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashiimport android.text.TextUtils; 43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateFormat; 44146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateUtils; 45146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time; 46146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.util.Log; 47146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ContextMenu; 48dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.view.ContextMenu.ContextMenuInfo; 49ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.GestureDetector; 50146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.Gravity; 51146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.KeyEvent; 52146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.LayoutInflater; 53146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.MenuItem; 54146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.MotionEvent; 55d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chanimport android.view.ScaleGestureDetector; 56146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.View; 57146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewConfiguration; 58146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewGroup; 59146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.WindowManager; 60ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.animation.Animation; 61ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.animation.TranslateAnimation; 62146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.ImageView; 63146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.PopupWindow; 64146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.TextView; 65ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.widget.ViewSwitcher; 66146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 67146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.ArrayList; 68c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawaimport java.util.Arrays; 69146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Calendar; 700d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chanimport java.util.regex.Matcher; 710d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chanimport java.util.regex.Pattern; 72146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 73146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/** 74d190418220467c02327dd9b3ae1eae238889720bMichael Chan * View for multi-day view. So far only 1 and 7 day have been tested. 75d190418220467c02327dd9b3ae1eae238889720bMichael Chan */ 76d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chanpublic class DayView extends View implements View.OnCreateContextMenuListener, 77d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan ScaleGestureDetector.OnScaleGestureListener, View.OnClickListener { 78d190418220467c02327dd9b3ae1eae238889720bMichael Chan private static String TAG = "DayView"; 79d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static boolean DEBUG = false; 80146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 81705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static float mScale = 0; // Used for supporting different screen densities 82666fc5e8ddbac15c951aad738bd818ee307eae42Erik private static final long INVALID_EVENT_ID = -1; //This is used for remembering a null event 83ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private static final long ANIMATION_DURATION = 400; 84705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 854484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_AGENDA = 2; 864484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_DAY = 3; 874484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_VIEW = 5; 884484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_CREATE = 6; 894484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_EDIT = 7; 904484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_DELETE = 8; 914484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan 9211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static int DEFAULT_CELL_HEIGHT = 64; 93d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int MAX_CELL_HEIGHT = 150; 94d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int MIN_Y_SPAN = 100; 95d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 96697157470a6f0d8e7b806af9b4fb7fbe0bccae87Erik 97146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mOnFlingCalled; 98666fc5e8ddbac15c951aad738bd818ee307eae42Erik /** 99666fc5e8ddbac15c951aad738bd818ee307eae42Erik * ID of the last event which was displayed with the toast popup. 100666fc5e8ddbac15c951aad738bd818ee307eae42Erik * 101666fc5e8ddbac15c951aad738bd818ee307eae42Erik * This is used to prevent popping up multiple quick views for the same event, especially 102666fc5e8ddbac15c951aad738bd818ee307eae42Erik * during calendar syncs. This becomes valid when an event is selected, either by default 103666fc5e8ddbac15c951aad738bd818ee307eae42Erik * on starting calendar or by scrolling to an event. It becomes invalid when the user 104666fc5e8ddbac15c951aad738bd818ee307eae42Erik * explicitly scrolls to an empty time slot, changes views, or deletes the event. 105666fc5e8ddbac15c951aad738bd818ee307eae42Erik */ 106666fc5e8ddbac15c951aad738bd818ee307eae42Erik private long mLastPopupEventID; 107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 108ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan protected Context mContext; 109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String[] CALENDARS_PROJECTION = new String[] { 111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Calendars._ID, // 0 112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Calendars.ACCESS_LEVEL, // 1 1136d34cec523930368976bc8d358d0a6de1da3462cMichael Chan Calendars.OWNER_ACCOUNT, // 2 114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int CALENDARS_INDEX_ACCESS_LEVEL = 1; 1166d34cec523930368976bc8d358d0a6de1da3462cMichael Chan private static final int CALENDARS_INDEX_OWNER_ACCOUNT = 2; 117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String CALENDARS_WHERE = Calendars._ID + "=%d"; 118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String[] ATTENDEES_PROJECTION = new String[] { 120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Attendees._ID, // 0 121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Attendees.ATTENDEE_RELATIONSHIP, // 1 122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int ATTENDEES_INDEX_RELATIONSHIP = 1; 124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=%d"; 125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_NONE = 0; 127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_ABOVE = 1; 128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_BELOW = 2; 129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_LEFT = 4; 130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_RIGHT = 8; 131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 132a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_NONE = 0; 133a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_DELETE = 1; 134a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_EDIT = 2; 135a505627659f6bfba8869eac8089f7030f2d0d92cErik 136705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static int HORIZONTAL_SCROLL_THRESHOLD = 50; 137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ContinueScroll mContinueScroll = new ContinueScroll(); 139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Make this visible within the package for more informative debugging 141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time mBaseDate; 142bd0e834aea317236d574f8738fe11a51fdc87968Erik private Time mCurrentTime; 143bd0e834aea317236d574f8738fe11a51fdc87968Erik //Update the current time line every five minutes if the window is left open that long 144bd0e834aea317236d574f8738fe11a51fdc87968Erik private static final int UPDATE_CURRENT_TIME_DELAY = 300000; 145bd0e834aea317236d574f8738fe11a51fdc87968Erik private UpdateCurrentTime mUpdateCurrentTime = new UpdateCurrentTime(); 146bd0e834aea317236d574f8738fe11a51fdc87968Erik private int mTodayJulianDay; 147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Typeface mBold = Typeface.DEFAULT_BOLD; 149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstJulianDay; 150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mLastJulianDay; 151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMonthLength; 153487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstVisibleDate; 154487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstVisibleDayOfWeek; 155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int[] mEarliestStartHour; // indexed by the week day offset 156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean[] mHasAllDayEvent; // indexed by the week day offset 157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 158731f1cb808b7586b93615b408ab2636081fab0dcErik private Runnable mTZUpdater = new Runnable() { 159731f1cb808b7586b93615b408ab2636081fab0dcErik @Override 160731f1cb808b7586b93615b408ab2636081fab0dcErik public void run() { 161731f1cb808b7586b93615b408ab2636081fab0dcErik String tz = Utils.getTimeZone(mContext, this); 162731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate.timezone = tz; 163731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate.normalize(true); 164731f1cb808b7586b93615b408ab2636081fab0dcErik mCurrentTime.switchTimezone(tz); 165731f1cb808b7586b93615b408ab2636081fab0dcErik invalidate(); 166731f1cb808b7586b93615b408ab2636081fab0dcErik } 167731f1cb808b7586b93615b408ab2636081fab0dcErik }; 168731f1cb808b7586b93615b408ab2636081fab0dcErik 169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * This variable helps to avoid unnecessarily reloading events by keeping 171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * track of the start millis parameter used for the most recent loading 172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * of events. If the next reload matches this, then the events are not 173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * reloaded. To force a reload, set this to zero (this is set to zero 174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * in the method clearCachedEvents()). 175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private long mLastReloadMillis; 177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ArrayList<Event> mEvents = new ArrayList<Event>(); 179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionDay; // Julian day 180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionHour; 181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean mSelectionAllDay; 183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1843eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan /** Width of a day or non-conflicting event */ 185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mCellWidth; 186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pre-allocate these objects and re-use them 188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mRect = new Rect(); 189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private RectF mRectF = new RectF(); 190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mSrcRect = new Rect(); 191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mDestRect = new Rect(); 192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mPaint = new Paint(); 193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mEventTextPaint = new Paint(); 194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mSelectionPaint = new Paint(); 195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Path mPath = new Path(); 196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 197ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan protected boolean mDrawTextInEventRect = true; 198487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstDayOfWeek; // First day of the week 199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private PopupWindow mPopup; 201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private View mPopupView; 202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The number of milliseconds to show the popup window 204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int POPUP_DISMISS_DELAY = 3000; 205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private DismissPopup mDismissPopup = new DismissPopup(); 206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mRemeasure = true; 208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private final EventLoader mEventLoader; 210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected final EventGeometry mEventGeometry; 211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static final int GRID_LINE_INNER_WIDTH = 1; 2133eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static final int GRID_LINE_WIDTH = 5; 2143eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int DAY_GAP = 1; 216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int HOUR_GAP = 1; 2179c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private static int SINGLE_ALLDAY_HEIGHT = 34; 2189c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private static int MAX_ALLDAY_HEIGHT = 100; 219705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static int ALLDAY_TOP_MARGIN = 3; 2209c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private static int MAX_ALLDAY_EVENT_HEIGHT = 34; 221e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* The extra space to leave above the text in all-day events */ 223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int ALL_DAY_TEXT_TOP_MARGIN = 0; 224e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* The extra space to leave above the text in normal events */ 226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int NORMAL_TEXT_TOP_MARGIN = 2; 227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int HOURS_LEFT_MARGIN = 2; 229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int HOURS_RIGHT_MARGIN = 4; 230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int HOURS_MARGIN = HOURS_LEFT_MARGIN + HOURS_RIGHT_MARGIN; 231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 232bd0e834aea317236d574f8738fe11a51fdc87968Erik private static int CURRENT_TIME_LINE_HEIGHT = 2; 233bd0e834aea317236d574f8738fe11a51fdc87968Erik private static int CURRENT_TIME_LINE_BORDER_WIDTH = 1; 2343eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static final int CURRENT_TIME_LINE_SIDE_BUFFER = 3; 235bd0e834aea317236d574f8738fe11a51fdc87968Erik 236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MINUTES_PER_HOUR = 60; 237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MINUTES_PER_DAY = MINUTES_PER_HOUR * 24; 238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_MINUTE = 60 * 1000; 239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_HOUR = (3600 * 1000); 240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_DAY = MILLIS_PER_HOUR * 24; 241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2423eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static final int DAY_HEADER_ALPHA = 0x26000000; 2433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static final int DAY_HEADER_TODAY_ALPHA = 0x99000000; 244c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // TODO replace event draws with assets 245c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik private static final int EVENT_OUTLINE_COLOR = 0x33333333; 24611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static float DAY_HEADER_ONE_DAY_LEFT_MARGIN = -12; 2473eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_ONE_DAY_RIGHT_MARGIN = 5; 2483eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_ONE_DAY_BOTTOM_MARGIN = 6; 2493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_LEFT_MARGIN = 5; 2503eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_RIGHT_MARGIN = 7; 2513eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_BOTTOM_MARGIN = 3; 2523eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_FONT_SIZE = 14; 2533eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DATE_HEADER_FONT_SIZE = 24; 2543eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float NORMAL_FONT_SIZE = 12; 2553eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float EVENT_TEXT_FONT_SIZE = 12; 2563eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float HOURS_FONT_SIZE = 12; 2573eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float AMPM_FONT_SIZE = 9; 258705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static int MIN_CELL_WIDTH_FOR_TEXT = 27; 259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int MAX_EVENT_TEXT_LEN = 500; 260705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static float MIN_EVENT_HEIGHT = 15.0F; // in pixels 2613eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float CALENDAR_COLOR_SQUARE_SIZE = 11; 262c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik private static float EVENT_RECT_TOP_MARGIN = 1; 26311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static float EVENT_RECT_BOTTOM_MARGIN = 1; 264c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik private static float EVENT_RECT_LEFT_MARGIN = 1; 26511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static float EVENT_RECT_RIGHT_MARGIN = 1; 26611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static float EVENT_TEXT_TOP_MARGIN = 8; 26711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static float EVENT_TEXT_BOTTOM_MARGIN = 5; 26811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static float EVENT_TEXT_LEFT_MARGIN = 8; 26911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static float EVENT_TEXT_RIGHT_MARGIN = 7; 2709c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private static float EVENT_ALL_DAY_TEXT_TOP_MARGIN = 4; 2719c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private static float EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN = 2; 2729c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private static float EVENT_ALL_DAY_TEXT_LEFT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 2739c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private static float EVENT_ALL_DAY_TEXT_RIGHT_MARGIN = EVENT_TEXT_RIGHT_MARGIN; 274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mSelectionColor; 276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mPressedColor; 277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mSelectedEventTextColor; 278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mEventTextColor; 27964b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok private static int mWeek_saturdayColor; 28064b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok private static int mWeek_sundayColor; 281d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarDateBannerTextColor; 2823eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarAllDayBackground; 283d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarAmPmLabel; 2843eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarDateBannerBackground; 28511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// private static int mCalendarDateSelected; 2863eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarGridAreaBackground; 287ba902466b19b11d587468e354edc58e542707747Michael Chan private static int mCalendarGridAreaSelected; 288d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarGridLineHorizontalColor; 289d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarGridLineVerticalColor; 2903eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int mCalendarGridLineInnerHorizontalColor; 2913eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int mCalendarGridLineInnerVerticalColor; 2923eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarHourBackground; 293d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarHourLabel; 29411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// private static int mCalendarHourSelected; 295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewStartX; 297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewStartY; 298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMaxViewStartY; 299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewHeight; 300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewWidth; 301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mGridAreaHeight; 302d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int mCellHeight = 0; // shared among all DayViews 303d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int mMinCellHeight = 32; 304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mScrollStartY; 305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mPreviousDirection; 306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 307d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** 308d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * Vertical distance or span between the two touch points at the start of a 309d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * scaling gesture 310d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan */ 311d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private float mStartingSpanY = 0; 312d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** Height of 1 hour in pixels at the start of a scaling gesture */ 313d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private int mCellHeightBeforeScaleGesture; 314d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** The hour at the center two touch points */ 315d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private float mGestureCenterHour = 0; 316d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** 317d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * Flag to decide whether to handle the up event. Cases where up events 318d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * should be ignored are 1) right after a scale gesture and 2) finger was 319d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * down before app launch 320d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan */ 321d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private boolean mHandleActionUp = true; 322d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mHoursTextHeight; 324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mEventTextAscent; 325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mEventTextHeight; 326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mAllDayHeight; 3273eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int DAY_HEADER_HEIGHT = 45; 328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMaxAllDayEvents; 329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected int mNumDays = 7; 331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mNumHours = 10; 3323eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 3333eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan /** Width of the time line (list of hours) to the left. */ 334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mHoursWidth; 335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mDateStrWidth; 336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstCell; 337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstHour = -1; 338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstHourOffset; 339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mHourStrs; 340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mDayStrs; 341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mDayStrs2Letter; 342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mIs24HourFormat; 343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private float[] mCharWidths = new float[MAX_EVENT_TEXT_LEN]; 345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ArrayList<Event> mSelectedEvents = new ArrayList<Event>(); 346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mComputeSelectedEvents; 347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Event mSelectedEvent; 348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Event mPrevSelectedEvent; 349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mPrevBox = new Rect(); 350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected final Resources mResources; 3513eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan protected final Drawable mCurrentTimeLine; 3523eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan protected final Drawable mTodayHeaderDrawable; 35311638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // TODO change back to using background image when we can make it fast enough 35411638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // protected final Drawable mBackgroundDrawable; 35511638ad4fb56b978770aebe75deac7a0e6ac60d2Erik protected int mBackgroundColor; 356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String mAmString; 357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String mPmString; 358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private DeleteEventHelper mDeleteEventHelper; 359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ContextMenuHandler mContextMenuHandler = new ContextMenuHandler(); 361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 362d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan ScaleGestureDetector mScaleGestureDetector; 363d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The initial state of the touch mode when we enter this view. 366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_INITIAL_STATE = 0; 368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates we just received the touch event and we are waiting to see if 371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * it is a tap or a scroll gesture. 372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_DOWN = 1; 374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates the touch gesture is a vertical scroll 377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_VSCROLL = 0x20; 379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates the touch gesture is a horizontal scroll 382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_HSCROLL = 0x40; 384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mTouchMode = TOUCH_MODE_INITIAL_STATE; 386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The selection modes are HIDDEN, PRESSED, SELECTED, and LONGPRESS. 389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_HIDDEN = 0; 391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_PRESSED = 1; 392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_SELECTED = 2; 393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_LONGPRESS = 3; 394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionMode = SELECTION_HIDDEN; 396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mScrolling = false; 398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 399ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private CalendarController mController; 400ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private ViewSwitcher mViewSwitcher; 401ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private GestureDetector mGestureDetector; 402705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 403d190418220467c02327dd9b3ae1eae238889720bMichael Chan public DayView(Context context, CalendarController controller, 40475d9b567e1fd3b9c6945cd0afe28781f5a19c6c8Michael Chan ViewSwitcher viewSwitcher, EventLoader eventLoader, int numDays) { 405ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan super(context); 406705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan if (mScale == 0) { 407705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan mScale = getContext().getResources().getDisplayMetrics().density; 408705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan if (mScale != 1) { 409705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan SINGLE_ALLDAY_HEIGHT *= mScale; 410705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan MAX_ALLDAY_HEIGHT *= mScale; 411705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan ALLDAY_TOP_MARGIN *= mScale; 412705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan MAX_ALLDAY_EVENT_HEIGHT *= mScale; 413705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 414705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan NORMAL_FONT_SIZE *= mScale; 415705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan EVENT_TEXT_FONT_SIZE *= mScale; 416705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan HOURS_FONT_SIZE *= mScale; 417705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan AMPM_FONT_SIZE *= mScale; 418705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan MIN_CELL_WIDTH_FOR_TEXT *= mScale; 419705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan MIN_EVENT_HEIGHT *= mScale; 420705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 421705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan HORIZONTAL_SCROLL_THRESHOLD *= mScale; 422e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 423bd0e834aea317236d574f8738fe11a51fdc87968Erik CURRENT_TIME_LINE_HEIGHT *= mScale; 424bd0e834aea317236d574f8738fe11a51fdc87968Erik CURRENT_TIME_LINE_BORDER_WIDTH *= mScale; 425bd0e834aea317236d574f8738fe11a51fdc87968Erik 426d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan MIN_Y_SPAN *= mScale; 427d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan MAX_CELL_HEIGHT *= mScale; 428697157470a6f0d8e7b806af9b4fb7fbe0bccae87Erik DEFAULT_CELL_HEIGHT *= mScale; 4293eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_HEIGHT *= mScale; 4303eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_LEFT_MARGIN *= mScale; 4313eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_RIGHT_MARGIN *= mScale; 4323eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_BOTTOM_MARGIN *= mScale; 4333eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_LEFT_MARGIN *= mScale; 4343eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_RIGHT_MARGIN *= mScale; 4353eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_BOTTOM_MARGIN *= mScale; 4363eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_FONT_SIZE *= mScale; 4373eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DATE_HEADER_FONT_SIZE *= mScale; 4383eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan CALENDAR_COLOR_SQUARE_SIZE *= mScale; 4393eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_TOP_MARGIN *= mScale; 4403eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_BOTTOM_MARGIN *= mScale; 4413eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_LEFT_MARGIN *= mScale; 4423eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_RIGHT_MARGIN *= mScale; 4439c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_TOP_MARGIN *= mScale; 4449c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN *= mScale; 4459c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_LEFT_MARGIN *= mScale; 4469c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_RIGHT_MARGIN *= mScale; 44711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_TOP_MARGIN *= mScale; 44811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_BOTTOM_MARGIN *= mScale; 44911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_LEFT_MARGIN *= mScale; 45011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_RIGHT_MARGIN *= mScale; 451705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan } 452705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan } 453705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 454ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mResources = context.getResources(); 4553eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine = mResources.getDrawable(R.drawable.timeline_week_holo_light); 4563eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable = mResources.getDrawable(R.drawable.today_blue_week_holo_light); 45711638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // mBackgroundDrawable = mResources.getDrawable(R.drawable.calendar_background_holo_light); 458ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mEventLoader = eventLoader; 459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry = new EventGeometry(); 460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setMinEventHeight(MIN_EVENT_HEIGHT); 461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setHourGap(HOUR_GAP); 462ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mContext = context; 463ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mDeleteEventHelper = new DeleteEventHelper(context, null, false /* don't exit when done */); 464666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 465ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mController = controller; 466ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher = viewSwitcher; 467ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector = new GestureDetector(context, new CalendarGestureListener()); 468d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mScaleGestureDetector = new ScaleGestureDetector(getContext(), this); 46975d9b567e1fd3b9c6945cd0afe28781f5a19c6c8Michael Chan mNumDays = numDays; 470d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight == 0) { 471d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = Utils.getSharedPreference(mContext, 472d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan GeneralPreferences.KEY_DEFAULT_CELL_HEIGHT, DEFAULT_CELL_HEIGHT); 473d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 475ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan init(context); 476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void init(Context context) { 479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setFocusable(true); 480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allow focus in touch mode so that we can do keyboard shortcuts 482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // even after we've entered touch mode. 483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setFocusableInTouchMode(true); 484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setClickable(true); 485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setOnCreateContextMenuListener(this); 486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 487487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstDayOfWeek = Utils.getFirstDayOfWeek(context); 488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 489731f1cb808b7586b93615b408ab2636081fab0dcErik mCurrentTime = new Time(Utils.getTimeZone(context, mTZUpdater)); 490bd0e834aea317236d574f8738fe11a51fdc87968Erik long currentTime = System.currentTimeMillis(); 491bd0e834aea317236d574f8738fe11a51fdc87968Erik mCurrentTime.set(currentTime); 492bd0e834aea317236d574f8738fe11a51fdc87968Erik //The % makes it go off at the next increment of 5 minutes. 493bd0e834aea317236d574f8738fe11a51fdc87968Erik postDelayed(mUpdateCurrentTime, 494bd0e834aea317236d574f8738fe11a51fdc87968Erik UPDATE_CURRENT_TIME_DELAY - (currentTime % UPDATE_CURRENT_TIME_DELAY)); 495bd0e834aea317236d574f8738fe11a51fdc87968Erik mTodayJulianDay = Time.getJulianDay(currentTime, mCurrentTime.gmtoff); 496bd0e834aea317236d574f8738fe11a51fdc87968Erik 49764b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok mWeek_saturdayColor = mResources.getColor(R.color.week_saturday); 49864b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok mWeek_sundayColor = mResources.getColor(R.color.week_sunday); 499d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarDateBannerTextColor = mResources.getColor(R.color.calendar_date_banner_text_color); 5003eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarAllDayBackground = mResources.getColor(R.color.calendar_all_day_background); 501d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarAmPmLabel = mResources.getColor(R.color.calendar_ampm_label); 5023eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarDateBannerBackground = mResources.getColor(R.color.calendar_date_banner_background); 50311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// mCalendarDateSelected = mResources.getColor(R.color.calendar_date_selected); 5043eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarGridAreaBackground = mResources.getColor(R.color.calendar_grid_area_background); 505ba902466b19b11d587468e354edc58e542707747Michael Chan mCalendarGridAreaSelected = mResources.getColor(R.color.calendar_grid_area_selected); 506d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarGridLineHorizontalColor = mResources.getColor(R.color.calendar_grid_line_horizontal_color); 507d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarGridLineVerticalColor = mResources.getColor(R.color.calendar_grid_line_vertical_color); 5083eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCalendarGridLineInnerHorizontalColor = mResources.getColor(R.color.calendar_grid_line_inner_horizontal_color); 5093eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCalendarGridLineInnerVerticalColor = mResources.getColor(R.color.calendar_grid_line_inner_vertical_color); 5103eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarHourBackground = mResources.getColor(R.color.calendar_hour_background); 511d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarHourLabel = mResources.getColor(R.color.calendar_hour_label); 51211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// mCalendarHourSelected = mResources.getColor(R.color.calendar_hour_selected); 513146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionColor = mResources.getColor(R.color.selection); 514146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPressedColor = mResources.getColor(R.color.pressed); 515146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEventTextColor = mResources.getColor(R.color.calendar_event_selected_text_color); 516146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextColor = mResources.getColor(R.color.calendar_event_text_color); 51711638ad4fb56b978770aebe75deac7a0e6ac60d2Erik 51811638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // TODO remove this 51911638ad4fb56b978770aebe75deac7a0e6ac60d2Erik mBackgroundColor = mResources.getColor(R.color.month_bgcolor); 52011638ad4fb56b978770aebe75deac7a0e6ac60d2Erik 521146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setColor(mEventTextColor); 522146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setTextSize(EVENT_TEXT_FONT_SIZE); 523146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setTextAlign(Paint.Align.LEFT); 524146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setAntiAlias(true); 525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int gridLineColor = mResources.getColor(R.color.calendar_grid_line_highlight_color); 527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mSelectionPaint; 528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setColor(gridLineColor); 5293937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setStyle(Style.FILL); 530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p = mPaint; 533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allocate space for 2 weeks worth of weekday names so that we can 536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // easily start the week display at any week day. 537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs = new String[14]; 538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also create an array of 2-letter abbreviations. 540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter = new String[14]; 541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) { 543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int index = i - Calendar.SUNDAY; 544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // e.g. Tue for Tuesday 545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_MEDIUM); 546146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs[index + 7] = mDayStrs[index]; 547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // e.g. Tu for Tuesday 548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_SHORT); 54952b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer 55052b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer // If we don't have 2-letter day strings, fall back to 1-letter. 55152b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer if (mDayStrs2Letter[index].equals(mDayStrs[index])) { 55252b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer mDayStrs2Letter[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_SHORTEST); 55352b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer } 55452b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer 555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter[index + 7] = mDayStrs2Letter[index]; 556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out how much space we need for the 3-letter abbrev names 559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // in the worst case. 5603eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] dateStrs = {" 28", " 30"}; 563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDateStrWidth = computeMaxStringWidth(0, dateStrs, p); 5643eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDateStrWidth += computeMaxStringWidth(0, mDayStrs, p); 566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(HOURS_FONT_SIZE); 568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(null); 56969ab334d6988eda70ba53618506d23ebf7d7b405Erik updateIs24HourFormat(); 570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAmString = DateUtils.getAMPMString(Calendar.AM); 572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPmString = DateUtils.getAMPMString(Calendar.PM); 573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] ampm = {mAmString, mPmString}; 574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(AMPM_FONT_SIZE); 575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHoursWidth = computeMaxStringWidth(mHoursWidth, ampm, p); 576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHoursWidth += HOURS_MARGIN; 577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project LayoutInflater inflater; 579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView = inflater.inflate(R.layout.bubble_event, null); 581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView.setLayoutParams(new ViewGroup.LayoutParams( 582df279e3f9d5b0f189f812c52aca78d18178e4445Romain Guy ViewGroup.LayoutParams.MATCH_PARENT, 583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ViewGroup.LayoutParams.WRAP_CONTENT)); 584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup = new PopupWindow(context); 585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setContentView(mPopupView); 586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Resources.Theme dialogTheme = getResources().newTheme(); 587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dialogTheme.applyStyle(android.R.style.Theme_Dialog, true); 588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TypedArray ta = dialogTheme.obtainStyledAttributes(new int[] { 589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project android.R.attr.windowBackground }); 590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setBackgroundDrawable(ta.getDrawable(0)); 591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ta.recycle(); 592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Enable touching the popup window 594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView.setOnClickListener(this); 595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 596731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate = new Time(Utils.getTimeZone(context, mTZUpdater)); 597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = System.currentTimeMillis(); 598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.set(millis); 599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour = new int[mNumDays]; 601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent = new boolean[mNumDays]; 602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * This is called when the popup window is pressed. 606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void onClick(View v) { 608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (v == mPopupView) { 609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pretend it was a trackball click because that will always 610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // jump to the "View event" screen. 611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball */); 612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 61569ab334d6988eda70ba53618506d23ebf7d7b405Erik public void updateIs24HourFormat() { 616ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mIs24HourFormat = DateFormat.is24HourFormat(mContext); 61769ab334d6988eda70ba53618506d23ebf7d7b405Erik mHourStrs = mIs24HourFormat ? CalendarData.s24Hours : CalendarData.s12HoursNoAmPm; 61869ab334d6988eda70ba53618506d23ebf7d7b405Erik } 61969ab334d6988eda70ba53618506d23ebf7d7b405Erik 620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Returns the start of the selected time in milliseconds since the epoch. 622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return selected time in UTC milliseconds since the epoch. 624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long getSelectedTimeInMillis() { 626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time.normalize(true /* ignore isDst */); 634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time getSelectedTime() { 637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 640146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 643146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 644146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.normalize(true /* ignore isDst */); 645146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time; 646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 647146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 648146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 649146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Returns the start of the selected time in minutes since midnight, 650146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * local time. The derived class must ensure that this is consistent 651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * with the return value from getSelectedTimeInMillis(). 652146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int getSelectedMinutesSinceMidnight() { 654146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return mSelectionHour * MINUTES_PER_HOUR; 655146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void setSelectedDay(Time time) { 658146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.set(time); 659146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mBaseDate.hour; 660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 661146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 662146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = mBaseDate.toMillis(false /* use isDst */); 663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = Time.getJulianDay(millis, mBaseDate.gmtoff); 664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 665146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Force a recalculation of the first visible hour 668146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = -1; 669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 670146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Force a redraw of the selection box. 672146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = true; 674146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 675146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 676146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 677146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public Time getSelectedDay() { 678146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 679146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 685146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.normalize(true /* ignore isDst */); 686146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time; 687146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 688146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 68983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan /** 690487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * return a negative number if "time" is comes before the visible time 691487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * range, a positive number if "time" is after the visible time range, and 0 692487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * if it is in the visible time range. 69383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan */ 694487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan public int compareToVisibleTimeRange(Time time) { 695487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 696487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedHour = mBaseDate.hour; 697487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedMinute = mBaseDate.minute; 698487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedSec = mBaseDate.second; 699487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 700487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.hour = 0; 701487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.minute = 0; 702487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.second = 0; 703487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 704487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan Log.d(TAG, "Begin " + mBaseDate.toString()); 705487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan Log.d(TAG, "Diff " + time.toString()); 706487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 70783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan // Compare beginning of range 70883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan int diff = Time.compare(time, mBaseDate); 709487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (diff > 0) { 710487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // Compare end of range 711487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.monthDay += mNumDays; 712487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.normalize(true); 713487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = Time.compare(time, mBaseDate); 714487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 715487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan Log.d(TAG, "End " + mBaseDate.toString()); 716487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 717487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.monthDay -= mNumDays; 718487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.normalize(true); 719487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (diff < 0) { 720487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // in visible time 721487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = 0; 722487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } else if (diff == 0) { 723487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // Midnight of following day 724487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = 1; 725487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 72683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 72783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 728487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan Log.d(TAG, "Diff: " + diff); 72983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 730487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.hour = savedHour; 731487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.minute = savedMinute; 732487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.second = savedSec; 733487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan return diff; 73483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 73583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 736146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void recalc() { 737146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Set the base date to the beginning of the week if we are displaying 738146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // 7 days at a time. 739146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 7) { 740146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int dayOfWeek = mBaseDate.weekDay; 741487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int diff = dayOfWeek - mFirstDayOfWeek; 742146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (diff != 0) { 743146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (diff < 0) { 744146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project diff += 7; 745146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 746146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.monthDay -= diff; 747146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.normalize(true /* ignore isDst */); 748146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 749146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 750146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 751146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final long start = mBaseDate.toMillis(false /* use isDst */); 752146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstJulianDay = Time.getJulianDay(start, mBaseDate.gmtoff); 753146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastJulianDay = mFirstJulianDay + mNumDays - 1; 754146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 755146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mMonthLength = mBaseDate.getActualMaximum(Time.MONTH_DAY); 756487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstVisibleDate = mBaseDate.monthDay; 757487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstVisibleDayOfWeek = mBaseDate.weekDay; 758146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 759146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 760146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 761146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected void onSizeChanged(int width, int height, int oldw, int oldh) { 762146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewWidth = width; 763146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewHeight = height; 764146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int gridAreaWidth = width - mHoursWidth; 765146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mCellWidth = (gridAreaWidth - (mNumDays * DAY_GAP)) / mNumDays; 766146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 767146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = new Paint(); 768146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(HOURS_FONT_SIZE); 769146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHoursTextHeight = (int) Math.abs(p.ascent()); 770146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 771146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(EVENT_TEXT_FONT_SIZE); 772146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float ascent = -p.ascent(); 773146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextAscent = (int) Math.ceil(ascent); 774146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float totalHeight = ascent + p.descent(); 775146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextHeight = (int) Math.ceil(totalHeight); 776146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 777146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project remeasure(width, height); 778146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 779146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 78046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa /** 78146b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa * Measures the space needed for various parts of the view after 78246b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa * loading new events. This can change if there are all-day events. 78346b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa */ 784146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void remeasure(int width, int height) { 785146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 786146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear the array of earliest start times, and the array 787146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // indicating presence of an all-day event. 788146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++) { 789146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[day] = 25; // some big number 790146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent[day] = false; 791146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 792146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 793d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // Compute the layout relation between each event before measuring cell 794d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // width, as the cell width should be adjusted along with the relation. 79546b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // 79646b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // Examples: A (1:00pm - 1:01pm), B (1:02pm - 2:00pm) 79746b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // We should mark them as "overwapped". Though they are not overwapped logically, but 79846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // minimum cell height implicitly expands the cell height of A and it should look like 79946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // (1:00pm - 1:15pm) after the cell height adjustment. 80046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa 801146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the space needed for the all-day events, if any. 802146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Make a pass over all the events, and keep track of the maximum 803146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // number of all-day events in any one day. Also, keep track of 804146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the earliest event in each day. 805146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxAllDayEvents = 0; 80646b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final ArrayList<Event> events = mEvents; 80746b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final int len = events.size(); 808c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa // Num of all-day-events on each day. 809c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int eventsCount[] = new int[mLastJulianDay - mFirstJulianDay + 1]; 810c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa Arrays.fill(eventsCount, 0); 811146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 812146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(ii); 813c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (event.startDay > mLastJulianDay || event.endDay < mFirstJulianDay) { 814146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 815c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 816146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.allDay) { 817c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int firstDay = Math.max(event.startDay, mFirstJulianDay); 818c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int lastDay = Math.min(event.endDay, mLastJulianDay); 819c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa for (int day = firstDay; day <= lastDay; day++) { 820c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int count = ++eventsCount[day - mFirstJulianDay]; 821c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (maxAllDayEvents < count) { 822c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa maxAllDayEvents = count; 823c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 824146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 825c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa 826146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = event.startDay - mFirstJulianDay; 827146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int durationDays = event.endDay - event.startDay + 1; 828146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum < 0) { 829146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project durationDays += daynum; 830146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project daynum = 0; 831146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 832146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum + durationDays > mNumDays) { 833146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project durationDays = mNumDays - daynum; 834146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 835146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = daynum; durationDays > 0; day++, durationDays--) { 836146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent[day] = true; 837146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = event.startDay - mFirstJulianDay; 840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int hour = event.startTime / 60; 841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum >= 0 && hour < mEarliestStartHour[daynum]) { 842146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[daynum] = hour; 843146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 844146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also check the end hour in case the event spans more than 846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // one day. 847146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project daynum = event.endDay - mFirstJulianDay; 848146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project hour = event.endTime / 60; 849146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum < mNumDays && hour < mEarliestStartHour[daynum]) { 850146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[daynum] = hour; 851146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 852146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 853146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mMaxAllDayEvents = maxAllDayEvents; 855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 8569c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan // Calculate mAllDayHeight 8573eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mFirstCell = DAY_HEADER_HEIGHT; 858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int allDayHeight = 0; 859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxAllDayEvents > 0) { 860146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is at most one all-day event per day, then use less 861146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // space (but more than the space for a single event). 862146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxAllDayEvents == 1) { 863146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project allDayHeight = SINGLE_ALLDAY_HEIGHT; 864146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 865146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allow the all-day area to grow in height depending on the 866146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // number of all-day events we need to show, up to a limit. 867146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project allDayHeight = maxAllDayEvents * MAX_ALLDAY_EVENT_HEIGHT; 868146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (allDayHeight > MAX_ALLDAY_HEIGHT) { 869146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project allDayHeight = MAX_ALLDAY_HEIGHT; 870146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 871146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 8723eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mFirstCell = DAY_HEADER_HEIGHT + allDayHeight + ALLDAY_TOP_MARGIN; 873146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 874146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = false; 875146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 876146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAllDayHeight = allDayHeight; 877146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 878146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mGridAreaHeight = height - mFirstCell; 879d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 880d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // The min is where 24 hours cover the entire visible area 881d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mMinCellHeight = mGridAreaHeight / 24 - HOUR_GAP + 1; 882d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight < mMinCellHeight) { 883d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = mMinCellHeight; 884d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 885d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 886697157470a6f0d8e7b806af9b4fb7fbe0bccae87Erik mNumHours = mGridAreaHeight / mCellHeight; 887146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setHourHeight(mCellHeight); 888146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 88927d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa final long minimumDurationMillis = (long) 89027d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa (MIN_EVENT_HEIGHT * DateUtils.MINUTE_IN_MILLIS / (mCellHeight / 60.0f)); 89146b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa Event.computePositions(events, minimumDurationMillis); 89246b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa 893c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Compute the top of our reachable view 894c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mMaxViewStartY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP) - mGridAreaHeight; 895d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 896d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.e(TAG, "mViewStartY: " + mViewStartY); 897d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.e(TAG, "mMaxViewStartY: " + mMaxViewStartY); 898d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 899d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mViewStartY > mMaxViewStartY) { 900d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = mMaxViewStartY; 901d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan computeFirstHour(); 902d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 903146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour == -1) { 905146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initFirstHour(); 906146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = 0; 907146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 908146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 909146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // When we change the base date, the number of all-day events may 910146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // change and that changes the cell height. When we switch dates, 911146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // we use the mFirstHourOffset from the previous view, but that may 912146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // be too large for the new view if the cell height is smaller. 913146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHourOffset >= mCellHeight + HOUR_GAP) { 914146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = mCellHeight + HOUR_GAP - 1; 915146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 916146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mFirstHour * (mCellHeight + HOUR_GAP) - mFirstHourOffset; 917146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 91846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final int eventAreaWidth = mNumDays * (mCellWidth + DAY_GAP); 919666fc5e8ddbac15c951aad738bd818ee307eae42Erik //When we get new events we don't want to dismiss the popup unless the event changes 920666fc5e8ddbac15c951aad738bd818ee307eae42Erik if (mSelectedEvent != null && mLastPopupEventID != mSelectedEvent.id) { 921666fc5e8ddbac15c951aad738bd818ee307eae42Erik mPopup.dismiss(); 922666fc5e8ddbac15c951aad738bd818ee307eae42Erik } 923146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setWidth(eventAreaWidth - 20); 924146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); 925146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 926146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 927146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 928146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Initialize the state for another view. The given view is one that has 929146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * its own bitmap and will use an animation to replace the current view. 930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The current view and new view are either both Week views or both Day 931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * views. They differ in their base date. 932146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 933146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param view the view to initialize. 934146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 935d190418220467c02327dd9b3ae1eae238889720bMichael Chan private void initView(DayView view) { 936146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionHour = mSelectionHour; 937146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectedEvents.clear(); 938146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mComputeSelectedEvents = true; 939146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mFirstHour = mFirstHour; 940146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mFirstHourOffset = mFirstHourOffset; 941146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.remeasure(getWidth(), getHeight()); 942e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 943146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectedEvent = null; 944146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mPrevSelectedEvent = null; 945487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan view.mFirstDayOfWeek = mFirstDayOfWeek; 946146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (view.mEvents.size() > 0) { 947146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionAllDay = mSelectionAllDay; 948146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 949146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionAllDay = false; 950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 951146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 952146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Redraw the screen so that the selection box will be redrawn. We may 953146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // have scrolled to a different part of the day in some other view 954146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // so the selection box in this view may no longer be visible. 955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.recalc(); 956146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 957146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 959146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Switch to another view based on what was selected (an event or a free 960146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * slot) and how it was selected (by touch or by trackball). 961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param trackBallSelection true if the selection was made using the 963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * trackball. 964146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void switchViews(boolean trackBallSelection) { 966146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 968146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 969666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 970146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays > 1) { 971146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the Week view. 972146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // With touch, we always switch to Day/Agenda View 973146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // With track ball, if we selected a free slot, then create an event. 974146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected a specific event, switch to EventInfo view. 975146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (trackBallSelection) { 976146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 977146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EditEvent view 978146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 979146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 9809e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 9819e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan startMillis, endMillis, 0, 0); 982146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 983146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EventInfo view 9849e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 9859e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan selectedEvent.startMillis, selectedEvent.endMillis, 0, 0); 986146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 987146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 988146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This was a touch selection. If the touch selected a single 989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // unambiguous event, then view that event. Otherwise go to 990146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Day/Agenda view. 991146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvents.size() == 1) { 9929e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 9939e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan selectedEvent.startMillis, selectedEvent.endMillis, 0, 0); 994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the Day view. 998146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected a free slot, then create an event. 999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected an event, then go to the EventInfo view. 1000146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 1001146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EditEvent view 1002146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 1003146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 10049e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan 10059e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, startMillis, 10069e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan endMillis, 0, 0); 1007146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 10089e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 10099e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan selectedEvent.startMillis, selectedEvent.endMillis, 0, 0); 1010146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1011146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1012146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1013146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1014146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1015146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 1016146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 1017146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long duration = event.getEventTime() - event.getDownTime(); 1018146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1019146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (keyCode) { 1020146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 1021146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_HIDDEN) { 1022146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Don't do anything unless the selection is visible. 1023146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1024146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1025146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1026146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_PRESSED) { 1027146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This was the first press when there was nothing selected. 1028146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Change the selection from the "pressed" state to the 1029146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the "selected" state. We treat short-press and 1030146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // long-press the same here because nothing was selected. 1031146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1032146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1033146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1034146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1035146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1036146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check the duration to determine if this was a short press 1037146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (duration < ViewConfiguration.getLongPressTimeout()) { 1038146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball */); 1039146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1040146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 1041146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1042146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project performLongClick(); 1043146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1044146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1045ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// case KeyEvent.KEYCODE_BACK: 1046ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// if (event.isTracking() && !event.isCanceled()) { 1047ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mPopup.dismiss(); 1048ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.finish(); 1049ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// return true; 1050ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// } 1051ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// break; 1052146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1053146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyUp(keyCode, event); 1054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1055146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1056146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1057146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 1058146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_HIDDEN) { 1059146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT 1060146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_UP 1061146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { 1062146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Display the selection box but don't move or select it 1063146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on this key press. 1064146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1065146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1066146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1067146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 1068146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Display the selection box but don't select it 1069146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on this key press. 1070146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_PRESSED; 1071146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1072146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1073146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1074146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1075146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1076146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 1078146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean redraw; 1079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectionDay = mSelectionDay; 1080146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1081146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (keyCode) { 1082146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DEL: 1083146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Delete the selected event, if any 1084146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 1085146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 1086146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return false; 1087146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1088146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 1089666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1090146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1091146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long begin = selectedEvent.startMillis; 1092146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long end = selectedEvent.endMillis; 1093146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long id = selectedEvent.id; 1094146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDeleteEventHelper.delete(begin, end, id, -1); 1095146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1096146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_ENTER: 1097146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball or keyboard */); 1098146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_BACK: 1100b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan if (event.getRepeatCount() == 0) { 1101b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan event.startTracking(); 1102b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan return true; 1103b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan } 1104b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan return super.onKeyDown(keyCode, event); 1105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_LEFT: 1106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 1107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = mSelectedEvent.nextLeft; 1108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 1110666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionDay -= 1; 1112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project redraw = true; 1114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_RIGHT: 1117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 1118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = mSelectedEvent.nextRight; 1119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 1121666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionDay += 1; 1123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project redraw = true; 1125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_UP: 1128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 1129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = mSelectedEvent.nextUp; 1130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 1132666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!mSelectionAllDay) { 1134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour -= 1; 1135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project adjustHourSelection(); 1136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project redraw = true; 1141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_DOWN: 1144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 1145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = mSelectedEvent.nextDown; 1146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 1148666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay) { 1150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = false; 1151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour++; 1153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project adjustHourSelection(); 1154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project redraw = true; 1159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project default: 1162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyDown(keyCode, event); 1163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((selectionDay < mFirstJulianDay) || (selectionDay > mLastJulianDay)) { 1166d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getNextView(); 1167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time date = view.mBaseDate; 1168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.set(mBaseDate); 1169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectionDay < mFirstJulianDay) { 1170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay -= mNumDays; 1171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay += mNumDays; 1173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.normalize(true /* ignore isDst */); 1175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = selectionDay; 1176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initView(view); 117883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 117983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time end = new Time(date); 118083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan end.monthDay += mNumDays - 1; 118183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Log.d(TAG, "onKeyDown"); 11823458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan mController.sendEvent(this, EventType.GO_TO, date, end, -1, ViewType.CURRENT); 1183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = selectionDay; 1186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (redraw) { 1190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyDown(keyCode, event); 1195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1197ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private View switchViews(boolean forward, float xOffSet, float width) { 1198ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float progress = Math.abs(xOffSet) / width; 1199ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (progress > 1.0f) { 1200ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan progress = 1.0f; 1201ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1202ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1203ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float inFromXValue, inToXValue; 1204ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float outFromXValue, outToXValue; 1205ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (forward) { 1206ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inFromXValue = 1.0f - progress; 1207ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inToXValue = 0.0f; 1208ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outFromXValue = -progress; 1209ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outToXValue = -1.0f; 1210ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } else { 1211ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inFromXValue = progress - 1.0f; 1212ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inToXValue = 0.0f; 1213ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outFromXValue = progress; 1214ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outToXValue = 1.0f; 1215ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1216ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1217ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // We have to allocate these animation objects each time we switch views 1218ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // because that is the only way to set the animation parameters. 1219ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan TranslateAnimation inAnimation = new TranslateAnimation( 1220ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, inFromXValue, 1221ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, inToXValue, 1222ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f, 1223ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f); 1224ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1225ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan TranslateAnimation outAnimation = new TranslateAnimation( 1226ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, outFromXValue, 1227ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, outToXValue, 1228ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f, 1229ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f); 1230ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1231ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // Reduce the animation duration based on how far we have already swiped. 1232ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan long duration = (long) (ANIMATION_DURATION * (1.0f - progress)); 1233ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inAnimation.setDuration(duration); 1234ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outAnimation.setDuration(duration); 1235ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.setInAnimation(inAnimation); 1236ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.setOutAnimation(outAnimation); 1237ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1238d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getCurrentView(); 1239ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.cleanup(); 1240ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.showNext(); 1241d190418220467c02327dd9b3ae1eae238889720bMichael Chan view = (DayView) mViewSwitcher.getCurrentView(); 1242ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.requestFocus(); 1243ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.reloadEvents(); 1244ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return view; 1245ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1246ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is called after scrolling stops to move the selected hour 1248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // to the visible part of the screen. 1249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void resetSelectedHour() { 1250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < mFirstHour + 1) { 1251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + 1; 1252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionHour > mFirstHour + mNumHours - 3) { 1256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + mNumHours - 3; 1257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void initFirstHour() { 1264d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mFirstHour = mSelectionHour - mNumHours / 5; 1265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 0) { 1266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = 0; 1267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mFirstHour + mNumHours > 24) { 1268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = 24 - mNumHours; 1269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Recomputes the first full hour that is visible on screen after the 1274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * screen is scrolled. 1275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeFirstHour() { 1277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the first full hour that is visible on screen 1278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = (mViewStartY + mCellHeight + HOUR_GAP - 1) / (mCellHeight + HOUR_GAP); 1279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = mFirstHour * (mCellHeight + HOUR_GAP) - mViewStartY; 1280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void adjustHourSelection() { 1283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < 0) { 1284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = 0; 1285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mMaxAllDayEvents > 0) { 1286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = true; 1288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour > 23) { 1292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = 23; 1293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the selected hour is at least 2 time slots from the top and 1296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // bottom of the screen, then don't scroll the view. 1297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < mFirstHour + 1) { 1298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there are all-days events for the selected day but there 1299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // are no more normal events earlier in the day, then jump to 1300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the all-day event area. 1301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Exception 1: allow the user to scroll to 8am with the trackball 1302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // before jumping to the all-day event area. 1303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Exception 2: if 12am is on screen, then allow the user to select 1304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // 12am before going up to the all-day event area. 1305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 1306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mMaxAllDayEvents > 0 && mEarliestStartHour[daynum] > mSelectionHour 1307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && mFirstHour > 0 && mFirstHour < 8) { 1308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = true; 1310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + 1; 1311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour > 0) { 1315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour -= 1; 1316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY -= (mCellHeight + HOUR_GAP); 1317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 1318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 1319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour > mFirstHour + mNumHours - 3) { 1325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 24 - mNumHours) { 1326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour += 1; 1327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY += (mCellHeight + HOUR_GAP); 1328c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik if (mViewStartY > mMaxViewStartY) { 1329c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mViewStartY = mMaxViewStartY; 1330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mFirstHour == 24 - mNumHours && mFirstHourOffset > 0) { 1333c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mViewStartY = mMaxViewStartY; 1334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project void clearCachedEvents() { 1339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastReloadMillis = 0; 1340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Runnable mCancelCallback = new Runnable() { 1343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 1344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project clearCachedEvents(); 1345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 1347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 134846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa /* package */ void reloadEvents() { 1349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against this being called before this view has been 1350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // initialized. 1351ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// if (mContext == null) { 1352ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// return; 1353ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// } 1354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1355731f1cb808b7586b93615b408ab2636081fab0dcErik // Make sure our time zones are up to date 1356731f1cb808b7586b93615b408ab2636081fab0dcErik mTZUpdater.run(); 1357731f1cb808b7586b93615b408ab2636081fab0dcErik 1358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The start date is the beginning of the week at 12am 1363731f1cb808b7586b93615b408ab2636081fab0dcErik Time weekStart = new Time(Utils.getTimeZone(mContext, mTZUpdater)); 1364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.set(mBaseDate); 1365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.hour = 0; 1366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.minute = 0; 1367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.second = 0; 1368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = weekStart.normalize(true /* ignore isDst */); 1369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Avoid reloading events unnecessarily. 1371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (millis == mLastReloadMillis) { 1372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastReloadMillis = millis; 1375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // load events in the background 1377ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.startProgressSpinner(); 1378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final ArrayList<Event> events = new ArrayList<Event>(); 1379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventLoader.loadEventsInBackground(mNumDays, events, millis, new Runnable() { 1380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 1381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEvents = events; 1382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = true; 1383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 1385ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.stopProgressSpinner(); 1386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }, mCancelCallback); 1389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected void onDraw(Canvas canvas) { 1393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mRemeasure) { 1394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project remeasure(getWidth(), getHeight()); 1395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = false; 1396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1397c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.save(); 1398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1399c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik float yTranslate = -mViewStartY + DAY_HEADER_HEIGHT + mAllDayHeight; 1400c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // offset canvas by the current drag and header position 1401c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(-mViewStartX, yTranslate); 1402c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // clip to everything below the allDay area 1403c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik Rect dest = mDestRect; 1404c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.top = (int) (mFirstCell - yTranslate); 1405c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.bottom = (int) (mViewHeight - yTranslate); 1406c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.left = 0; 1407c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.right = mViewWidth; 1408c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.save(); 1409c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.clipRect(dest); 1410c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Draw the movable part of the view 1411c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik doDraw(canvas); 1412c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // restore to having no clip 1413c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.restore(); 1414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 1416c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik float xTranslate; 1417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartX > 0) { 1418c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik xTranslate = mViewWidth; 1419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1420c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik xTranslate = -mViewWidth; 1421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1422c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Move the canvas around to prep it for the next view 1423c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // specifically, shift it by a screen and undo the 1424c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // yTranslation which will be redone in the nextView's onDraw(). 1425c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(xTranslate, -yTranslate); 1426d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView nextView = (DayView) mViewSwitcher.getNextView(); 1427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Prevent infinite recursive calls to onDraw(). 1429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project nextView.mTouchMode = TOUCH_MODE_INITIAL_STATE; 1430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project nextView.onDraw(canvas); 1432c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Move it back for this view 1433c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(-xTranslate, 0); 1434c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik } else { 1435c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // If we drew another view we already translated it back 1436c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // If we didn't draw another view we should be at the edge of the 1437c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // screen 1438c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(mViewStartX, -yTranslate); 1439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the fixed areas (that don't scroll) directly to the canvas. 1442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAfterScroll(canvas); 1443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = false; 1444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.restore(); 1445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAfterScroll(Canvas canvas) { 1448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mPaint; 1449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r = mRect; 1450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mMaxAllDayEvents != 0) { 1452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAllDayEvents(mFirstJulianDay, mNumDays, r, canvas, p); 14533eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// drawUpperLeftCorner(r, canvas, p); 1454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1456c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik drawScrollLine(r, canvas, p); 1457c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik 14583eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan drawDayHeaderLoop(r, canvas, p); 1459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the AM and PM indicators if we're in 12 hour mode 1461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!mIs24HourFormat) { 1462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAmPm(canvas, p); 1463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Update the popup window showing the event details, but only if 1466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // we are not scrolling and we have focus. 1467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!mScrolling && isFocused()) { 1468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project updateEventDetails(); 1469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This isn't really the upper-left corner. It's the square area just 1473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // below the upper-left corner, above the hours and to the left of the 1474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // all-day area. 14753eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private void drawUpperLeftCorner(Rect r, Canvas canvas, Paint p) { 14763eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// p.setColor(mCalendarHourBackground); 14773eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// r.top = DAY_HEADER_HEIGHT; 14783eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// r.bottom = r.top + mAllDayHeight + ALLDAY_TOP_MARGIN; 14793eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// r.left = 0; 14803eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// r.right = mHoursWidth; 14813eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// canvas.drawRect(r, p); 14823eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// } 1483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1484c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // TODO cleanup and constant extraction 1485c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik private void drawScrollLine(Rect r, Canvas canvas, Paint p) { 1486c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setColor(EVENT_OUTLINE_COLOR); 1487c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setStyle(Style.FILL); 1488c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(false); 1489c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik r.left = 0; 1490c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik r.right = mViewWidth; 1491c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik r.top = mFirstCell - 1; 1492c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik r.bottom = mFirstCell + 1; 1493c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.drawRect(r, p); 1494c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(true); 1495c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik } 1496c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik 1497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawDayHeaderLoop(Rect r, Canvas canvas, Paint p) { 1498146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the horizontal day background banner 14993eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarDateBannerBackground); 15003eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = 0; 15013eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = DAY_HEADER_HEIGHT; 15023eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = 0; 15033eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mHoursWidth + mNumDays * (mCellWidth + DAY_GAP); 15043eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 15053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // 1506146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the extra space on the right side with the default background 15073eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = r.right; 15083eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mViewWidth; 15093eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 15103eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 15123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int todayNum = mTodayJulianDay - mFirstJulianDay; 15133eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mNumDays > 1) { 15143eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.top = 0; 15153eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.bottom = DAY_HEADER_HEIGHT; 15163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 15173eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Highlight today 15183eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mFirstJulianDay <= mTodayJulianDay 15193eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan && mTodayJulianDay < (mFirstJulianDay + mNumDays)) { 15203eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.left = mHoursWidth + todayNum * (mCellWidth + DAY_GAP); 15213eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.right = r.left + mCellWidth; 15223eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable.setBounds(r); 15233eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable.draw(canvas); 15243eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 15253eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 15263eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw a highlight on the selected day (if any), but only if we are 15273eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // displaying more than one day. 152811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // 152911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // int selectedDayNum = mSelectionDay - mFirstJulianDay; 153011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // if (mSelectionMode != SELECTION_HIDDEN && selectedDayNum >= 0 153111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // && selectedDayNum < mNumDays) { 153211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // p.setColor(mCalendarDateSelected); 153311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // r.left = mHoursWidth + selectedDayNum * (mCellWidth + DAY_GAP); 153411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // r.right = r.left + mCellWidth; 153511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // canvas.drawRect(r, p); 153611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // } 1537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 15393eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTypeface(mBold); 15403eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextAlign(Paint.Align.RIGHT); 15413eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float x = mHoursWidth; 1542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaX = mCellWidth + DAY_GAP; 1543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cell = mFirstJulianDay; 1544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] dayNames; 1546146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mDateStrWidth < mCellWidth) { 1547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dayNames = mDayStrs; 1548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dayNames = mDayStrs2Letter; 1550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1552d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setAntiAlias(true); 1553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++, cell++) { 15541f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan int dayOfWeek = day + mFirstVisibleDayOfWeek; 15551f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan if (dayOfWeek >= 14) { 15561f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan dayOfWeek -= 14; 1557487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 1558487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 15593eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int color = mCalendarDateBannerTextColor; 1560487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (Utils.isSaturday(dayOfWeek, mFirstDayOfWeek)) { 15613eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan color = mWeek_saturdayColor; 1562487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } else if (Utils.isSunday(dayOfWeek, mFirstDayOfWeek)) { 15633eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan color = mWeek_sundayColor; 15643eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 15653eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 15663eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan color &= 0x00FFFFFF; 15673eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (todayNum == day) { 15683eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan color |= DAY_HEADER_TODAY_ALPHA; 1569487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } else { 15703eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan color |= DAY_HEADER_ALPHA; 1571487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 1572487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 15733eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(color); 1574487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan drawDayHeader(dayNames[dayOfWeek], day, cell, x, canvas, p); 1575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project x += deltaX; 1576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 15773eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTypeface(null); 1578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAmPm(Canvas canvas, Paint p) { 1581d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarAmPmLabel); 1582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(AMPM_FONT_SIZE); 1583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 1584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 1585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPaint.setTextAlign(Paint.Align.RIGHT); 1586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String text = mAmString; 1587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour >= 12) { 1588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = mPmString; 1589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = mFirstCell + mFirstHourOffset + 2 * mHoursTextHeight + HOUR_GAP; 1591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int right = mHoursWidth - HOURS_RIGHT_MARGIN; 1592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.drawText(text, right, y, p); 1593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 12 && mFirstHour + mNumHours > 12) { 1595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also draw the "PM" 1596146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = mPmString; 1597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y = mFirstCell + mFirstHourOffset + (12 - mFirstHour) * (mCellHeight + HOUR_GAP) 1598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project + 2 * mHoursTextHeight + HOUR_GAP; 1599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.drawText(text, right, y, p); 1600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 16033eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private void drawCurrentTimeLine(Rect r, final int left, final int top, Canvas canvas, Paint p) { 16043eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.left = left - CURRENT_TIME_LINE_SIDE_BUFFER; 16053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.right = left + mCellWidth + CURRENT_TIME_LINE_SIDE_BUFFER; 16063eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 16073eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.top = top - mCurrentTimeLine.getIntrinsicHeight() / 2; 16083eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.bottom = r.top + mCurrentTimeLine.getIntrinsicHeight(); 1609bd0e834aea317236d574f8738fe11a51fdc87968Erik 16103eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine.setBounds(r); 16113eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine.draw(canvas); 1612bd0e834aea317236d574f8738fe11a51fdc87968Erik } 1613bd0e834aea317236d574f8738fe11a51fdc87968Erik 1614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void doDraw(Canvas canvas) { 1615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mPaint; 1616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r = mRect; 1617bd0e834aea317236d574f8738fe11a51fdc87968Erik int lineY = mCurrentTime.hour*(mCellHeight + HOUR_GAP) 1618bd0e834aea317236d574f8738fe11a51fdc87968Erik + ((mCurrentTime.minute * mCellHeight) / 60) 1619bd0e834aea317236d574f8738fe11a51fdc87968Erik + 1; 1620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawGridBackground(r, canvas, p); 1622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawHours(r, canvas, p); 1623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw each day 1625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int x = mHoursWidth; 1626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaX = mCellWidth + DAY_GAP; 1627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cell = mFirstJulianDay; 1628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++, cell++) { 1629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawEvents(cell, x, HOUR_GAP, canvas, p); 1630bd0e834aea317236d574f8738fe11a51fdc87968Erik //If this is today 1631bd0e834aea317236d574f8738fe11a51fdc87968Erik if(cell == mTodayJulianDay) { 1632bd0e834aea317236d574f8738fe11a51fdc87968Erik //And the current time shows up somewhere on the screen 1633bd0e834aea317236d574f8738fe11a51fdc87968Erik if(lineY >= mViewStartY && lineY < mViewStartY + mViewHeight - 2) { 1634bd0e834aea317236d574f8738fe11a51fdc87968Erik drawCurrentTimeLine(r, x, lineY, canvas, p); 1635bd0e834aea317236d574f8738fe11a51fdc87968Erik } 1636bd0e834aea317236d574f8738fe11a51fdc87968Erik } 1637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project x += deltaX; 1638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1640146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawHours(Rect r, Canvas canvas, Paint p) { 16423eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Comment out as the background will be a drawable 16433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 1644146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the background for the hour labels 16453eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarHourBackground); 16463eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = 0; 16473eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = 24 * (mCellHeight + HOUR_GAP) + HOUR_GAP; 16483eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = 0; 16493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mHoursWidth; 16503eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1652146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the bottom left corner with the default grid background 16533eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = r.bottom; 16543eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = mBitmapHeight; 16553eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 16563eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1658146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw a highlight on the selected hour (if needed) 1659ba902466b19b11d587468e354edc58e542707747Michael Chan if (mSelectionMode != SELECTION_HIDDEN && !mSelectionAllDay) { 1660ba902466b19b11d587468e354edc58e542707747Michael Chan // p.setColor(mCalendarHourSelected); 16613937a47bc5a1afb9701e1d0565fae31f5800590dErik int daynum = mSelectionDay - mFirstJulianDay; 1662ba902466b19b11d587468e354edc58e542707747Michael Chan r.top = mSelectionHour * (mCellHeight + HOUR_GAP); 1663ba902466b19b11d587468e354edc58e542707747Michael Chan r.bottom = r.top + mCellHeight + 2 * HOUR_GAP; 16643937a47bc5a1afb9701e1d0565fae31f5800590dErik r.left = mHoursWidth + daynum * (mCellWidth + DAY_GAP) - DAY_GAP; 16653937a47bc5a1afb9701e1d0565fae31f5800590dErik r.right = r.left + mCellWidth + DAY_GAP; 1666ba902466b19b11d587468e354edc58e542707747Michael Chan 1667ba902466b19b11d587468e354edc58e542707747Michael Chan // Draw a border around the highlighted grid hour. 1668ba902466b19b11d587468e354edc58e542707747Michael Chan Path path = mPath; 1669ba902466b19b11d587468e354edc58e542707747Michael Chan path.reset(); 1670ba902466b19b11d587468e354edc58e542707747Michael Chan path.addRect(r.left, r.top, r.right, r.bottom, Direction.CW); 1671ba902466b19b11d587468e354edc58e542707747Michael Chan canvas.drawPath(path, mSelectionPaint); 1672ba902466b19b11d587468e354edc58e542707747Michael Chan saveSelectionPosition(r.left, r.top, r.right, r.bottom); 16733937a47bc5a1afb9701e1d0565fae31f5800590dErik 16743937a47bc5a1afb9701e1d0565fae31f5800590dErik // Also draw the highlight on the grid 16753937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setColor(mCalendarGridAreaSelected); 16763937a47bc5a1afb9701e1d0565fae31f5800590dErik r.top += HOUR_GAP; 16773937a47bc5a1afb9701e1d0565fae31f5800590dErik r.bottom -= HOUR_GAP; 16783937a47bc5a1afb9701e1d0565fae31f5800590dErik r.left += DAY_GAP; 16793937a47bc5a1afb9701e1d0565fae31f5800590dErik r.right -= DAY_GAP; 16803937a47bc5a1afb9701e1d0565fae31f5800590dErik canvas.drawRect(r, p); 1681ba902466b19b11d587468e354edc58e542707747Michael Chan } 1682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1683d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarHourLabel); 1684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(HOURS_FONT_SIZE); 1685146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 1686146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextAlign(Paint.Align.RIGHT); 1687146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 1688146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1689146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int right = mHoursWidth - HOURS_RIGHT_MARGIN; 1690146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = HOUR_GAP + mHoursTextHeight; 1691146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1692146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < 24; i++) { 1693146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String time = mHourStrs[i]; 1694146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.drawText(time, right, y, p); 1695146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += mCellHeight + HOUR_GAP; 1696146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1697146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1698146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 16993eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private void drawDayHeader(String dayStr, int day, int cell, float x, Canvas canvas, Paint p) { 1700487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int dateNum = mFirstVisibleDate + day; 1701146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (dateNum > mMonthLength) { 1702146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dateNum -= mMonthLength; 1703146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1704146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 17063eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan String dateNumStr = String.valueOf(dateNum); 17073eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mNumDays > 1) { 17083eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float y = DAY_HEADER_HEIGHT - DAY_HEADER_BOTTOM_MARGIN; 17093eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 17103eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 17113eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += mCellWidth - DAY_HEADER_RIGHT_MARGIN; 17123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 17133eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dateNumStr, x, y, p); 17143eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 17153eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the week 17163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x -= p.measureText(dateNumStr) + DAY_HEADER_LEFT_MARGIN; 17173eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 17183eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dayStr, x, y, p); 1719146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 17203eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float y = DAY_HEADER_HEIGHT - DAY_HEADER_ONE_DAY_BOTTOM_MARGIN; 172111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setTextAlign(Paint.Align.LEFT); 1722146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17233eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the week 17243eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += DAY_HEADER_ONE_DAY_LEFT_MARGIN; 17253eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 17263eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dayStr, x, y, p); 1727d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan 17283eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 17293eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += p.measureText(dayStr) + DAY_HEADER_ONE_DAY_RIGHT_MARGIN; 17303eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 17313eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dateNumStr, x, y, p); 1732d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan } 1733146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1734146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1735146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawGridBackground(Rect r, Canvas canvas, Paint p) { 1736146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint.Style savedStyle = p.getStyle(); 1737146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17383937a47bc5a1afb9701e1d0565fae31f5800590dErik// r.top = 0; 17393937a47bc5a1afb9701e1d0565fae31f5800590dErik// r.bottom = mMaxViewStartY + mGridAreaHeight; 17403937a47bc5a1afb9701e1d0565fae31f5800590dErik// r.left = 0; 17413937a47bc5a1afb9701e1d0565fae31f5800590dErik// r.right = mViewWidth; 17423eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 17433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 174411638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // TODO readd code for drawing bg image instead of color 174511638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // mBackgroundDrawable.setBounds(r); 174611638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // mBackgroundDrawable.draw(canvas); 1747c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik// p.setAntiAlias(false); 1748c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik// p.setColor(0x00000000); 1749c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik// p.setStyle(Style.FILL); 1750c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik// canvas.drawRect(r, p); 1751146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17523eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the outer horizontal grid lines 1753d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarGridLineHorizontalColor); 17549c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan p.setStyle(Style.FILL); 17553937a47bc5a1afb9701e1d0565fae31f5800590dErik 1756146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 17573eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startX = 0; 17583eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopX = mHoursWidth + (mCellWidth + DAY_GAP) * mNumDays; 1759146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float y = 0; 17603eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaY = mCellHeight + HOUR_GAP; 17613937a47bc5a1afb9701e1d0565fae31f5800590dErik r.left = (int) startX; 17623937a47bc5a1afb9701e1d0565fae31f5800590dErik r.right = (int) stopX; 17633937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setStrokeWidth(GRID_LINE_WIDTH); 1764146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int hour = 0; hour <= 24; hour++) { 17653937a47bc5a1afb9701e1d0565fae31f5800590dErik r.top = (int) (y - GRID_LINE_WIDTH / 2); 17663937a47bc5a1afb9701e1d0565fae31f5800590dErik r.bottom = r.top + GRID_LINE_WIDTH; 17673937a47bc5a1afb9701e1d0565fae31f5800590dErik // TODO use drawLine after Romain fixes drawing bug 17683937a47bc5a1afb9701e1d0565fae31f5800590dErik canvas.drawRect(r, p); 17693937a47bc5a1afb9701e1d0565fae31f5800590dErik// canvas.drawLine(startX, y, stopX, y, p); 1770146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += deltaY; 1771146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1772146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17733eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the outer vertical grid lines 1774d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarGridLineVerticalColor); 17753eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startY = 0; 17763eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP); 17773eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaX = mCellWidth + DAY_GAP; 1778146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float x = mHoursWidth + mCellWidth; 1779146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++) { 1780146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.drawLine(x, startY, x, stopY, p); 1781146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project x += deltaX; 1782146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1783146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17843eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner horizontal grid lines 17853eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerHorizontalColor); 17863eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 17873eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan y = 0; 17883eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x = 0; 17893eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int hour = 0; hour <= 24; hour++) { 17903eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawLine(startX, y, stopX, y, p); 17913eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan y += deltaY; 17923eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 17933eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 17943eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner vertical grid lines 17953eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerVerticalColor); 17963eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x = mHoursWidth + mCellWidth; 17973eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int day = 0; day < mNumDays; day++) { 17983eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawLine(x, startY, x, stopY, p); 17993eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += deltaX; 18003eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 18013eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 1802146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Restore the saved style. 1803146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setStyle(savedStyle); 1804146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 1805146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1806146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1807146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event getSelectedEvent() { 1808146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 1809146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // There is no event at the selected hour, so create a new event. 1810146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return getNewEvent(mSelectionDay, getSelectedTimeInMillis(), 1811146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getSelectedMinutesSinceMidnight()); 1812146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1813146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return mSelectedEvent; 1814146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1815146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1816146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean isEventSelected() { 1817146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return (mSelectedEvent != null); 1818146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1819146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event getNewEvent() { 1821146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return getNewEvent(mSelectionDay, getSelectedTimeInMillis(), 1822146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getSelectedMinutesSinceMidnight()); 1823146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1824146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1825146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project static Event getNewEvent(int julianDay, long utcMillis, 1826146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int minutesSinceMidnight) { 1827146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = Event.newInstance(); 1828146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startDay = julianDay; 1829146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endDay = julianDay; 1830146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startMillis = utcMillis; 1831146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endMillis = event.startMillis + MILLIS_PER_HOUR; 1832146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startTime = minutesSinceMidnight; 1833146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endTime = event.startTime + MINUTES_PER_HOUR; 1834146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return event; 1835146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1836146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1837146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int computeMaxStringWidth(int currentMax, String[] strings, Paint p) { 1838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float maxWidthF = 0.0f; 1839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = strings.length; 1841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < len; i++) { 1842146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float width = p.measureText(strings[i]); 1843146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxWidthF = Math.max(width, maxWidthF); 1844146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxWidth = (int) (maxWidthF + 0.5); 1846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxWidth < currentMax) { 1847146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxWidth = currentMax; 1848146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1849146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return maxWidth; 1850146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1851146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1852146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void saveSelectionPosition(float left, float top, float right, float bottom) { 1853146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.left = (int) left; 1854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.right = (int) right; 1855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.top = (int) top; 1856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.bottom = (int) bottom; 1857146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect getCurrentSelectionPosition() { 1860146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect box = new Rect(); 1861146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.top = mSelectionHour * (mCellHeight + HOUR_GAP); 1862146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.bottom = box.top + mCellHeight + HOUR_GAP; 1863146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 1864146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.left = mHoursWidth + daynum * (mCellWidth + DAY_GAP); 1865146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.right = box.left + mCellWidth + DAY_GAP; 1866146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return box; 1867146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1868146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 18699c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private void setupTextRect(RectF rf) { 18709c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.top += EVENT_TEXT_TOP_MARGIN; 18719c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.bottom -= EVENT_TEXT_BOTTOM_MARGIN; 18729c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.left += EVENT_TEXT_LEFT_MARGIN; 18739c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.right -= EVENT_TEXT_RIGHT_MARGIN; 18749c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan } 18759c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan 18769c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private void setupAllDayTextRect(RectF rf) { 18779c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.top += EVENT_ALL_DAY_TEXT_TOP_MARGIN; 18789c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.bottom -= EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN; 18799c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.left += EVENT_ALL_DAY_TEXT_LEFT_MARGIN; 18809c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.right -= EVENT_ALL_DAY_TEXT_RIGHT_MARGIN; 18819c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan } 18829c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan 1883146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAllDayEvents(int firstDay, int numDays, 1884146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r, Canvas canvas, Paint p) { 1885146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(NORMAL_FONT_SIZE); 1886146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextAlign(Paint.Align.LEFT); 1887146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint eventTextPaint = mEventTextPaint; 1888146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1889146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the background for the all-day events area 18903eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = DAY_HEADER_HEIGHT; 18913eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = r.top + mAllDayHeight + ALLDAY_TOP_MARGIN; 18923eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = mHoursWidth; 18933eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = r.left + mNumDays * (mCellWidth + DAY_GAP); 18943eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarAllDayBackground); 18953eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1896146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1897146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the extra space on the right side with the default background 18983eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = r.right; 18993eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mViewWidth; 19003eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 19013eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1902146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 19033eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the outer vertical grid lines 1904d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarGridLineVerticalColor); 19059c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan p.setStyle(Style.FILL); 19063eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_WIDTH); 1907146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 19083eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startY = DAY_HEADER_HEIGHT; 19093eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopY = startY + mAllDayHeight + ALLDAY_TOP_MARGIN; 19103eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaX = mCellWidth + DAY_GAP; 1911146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float x = mHoursWidth + mCellWidth; 19123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int day = 0; day < mNumDays; day++) { 1913146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.drawLine(x, startY, x, stopY, p); 1914146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project x += deltaX; 1915146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 19163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 19173eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner vertical grid lines 19183eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerVerticalColor); 19193eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x = mHoursWidth + mCellWidth; 19203eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 19213eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int day = 0; day < mNumDays; day++) { 19223eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawLine(x, startY, x, stopY, p); 19233eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += deltaX; 19243eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 19253eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 1926146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 1927146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setStyle(Style.FILL); 1928146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 19293eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int y = DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 1930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float left = mHoursWidth; 1931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int lastDay = firstDay + numDays - 1; 1932146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ArrayList<Event> events = mEvents; 1933146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 1934146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float drawHeight = mAllDayHeight; 1935146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float numRectangles = mMaxAllDayEvents; 1936146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 1937146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 1938c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (!event.allDay) { 1939146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 1940c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 1941146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startDay = event.startDay; 1942146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endDay = event.endDay; 1943c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (startDay > lastDay || endDay < firstDay) { 1944146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 1945c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 1946c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (startDay < firstDay) { 1947146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startDay = firstDay; 1948c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 1949c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (endDay > lastDay) { 1950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endDay = lastDay; 1951c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 1952146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startIndex = startDay - firstDay; 1953146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endIndex = endDay - firstDay; 1954146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float height = drawHeight / numRectangles; 1955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1956146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Prevent a single event from getting too big 1957146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (height > MAX_ALLDAY_EVENT_HEIGHT) { 1958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project height = MAX_ALLDAY_EVENT_HEIGHT; 1959146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1960146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Leave a one-pixel space between the vertical day lines and the 1962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event rectangle. 19639c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan event.left = left + startIndex * (mCellWidth + DAY_GAP); 19649c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan event.right = left + endIndex * (mCellWidth + DAY_GAP) + mCellWidth; 1965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.top = y + height * event.getColumn(); 19669c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan event.bottom = event.top + height; 1967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 19689c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan RectF rf = drawEventRect(event, canvas, p, eventTextPaint); 19699c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan setupAllDayTextRect(rf); 1970146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawEventText(event, rf, canvas, eventTextPaint, ALL_DAY_TEXT_TOP_MARGIN); 1971146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1972146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check if this all-day event intersects the selected day 1973146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay && mComputeSelectedEvents) { 1974146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (startDay <= mSelectionDay && endDay >= mSelectionDay) { 1975146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 1976146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1977146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1978146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1979146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1980146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay) { 1981146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the neighbors for the list of all-day events that 1982146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // intersect the selected day. 1983146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeAllDayNeighbors(); 1984146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 1985146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = mSelectedEvent; 19869c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan RectF rf = drawEventRect(event, canvas, p, eventTextPaint); 19879c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan setupAllDayTextRect(rf); 1988146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawEventText(event, rf, canvas, eventTextPaint, ALL_DAY_TEXT_TOP_MARGIN); 1989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1990146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1991146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the highlight on the selected all-day area 19923eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float top = DAY_HEADER_HEIGHT + 1; 1993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float bottom = top + mAllDayHeight + ALLDAY_TOP_MARGIN - 1; 1994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 1995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project left = mHoursWidth + daynum * (mCellWidth + DAY_GAP) + 1; 1996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float right = left + mCellWidth + DAY_GAP - 1; 1997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 1) { 1998146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The Day view doesn't have a vertical line on the right. 1999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project right -= 1; 2000146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2001146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Path path = mPath; 2002146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project path.reset(); 2003146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project path.addRect(left, top, right, bottom, Direction.CW); 2004146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.drawPath(path, mSelectionPaint); 2005146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2006146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Set the selection position to zero so that when we move down 2007146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // to the normal event area, we will highlight the topmost event. 2008146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project saveSelectionPosition(0f, 0f, 0f, 0f); 2009146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2010146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2011146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2012146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeAllDayNeighbors() { 2013146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 2014146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len == 0 || mSelectedEvent != null) { 2015146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2016146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2017146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2018146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear all the links 2019146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2020146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2021146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = null; 2022146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = null; 2023146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = null; 2024146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = null; 2025146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2026146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2027146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each event in the selected event list "mSelectedEvents", find 2028146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // its neighbors in the up and down directions. This could be done 2029146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // more efficiently by sorting on the Event.getColumn() field, but 2030146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the list is expected to be very small. 2031146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2032146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Find the event in the same row as the previously selected all-day 2033146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event, if any. 2034146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startPosition = -1; 2035146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPrevSelectedEvent != null && mPrevSelectedEvent.allDay) { 2036146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startPosition = mPrevSelectedEvent.getColumn(); 2037146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2038146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxPosition = -1; 2039146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event startEvent = null; 2040146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event maxPositionEvent = null; 2041146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2042146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2043146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int position = ev.getColumn(); 2044146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (position == startPosition) { 2045146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEvent = ev; 2046146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (position > maxPosition) { 2047146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxPositionEvent = ev; 2048146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxPosition = position; 2049146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2050146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int jj = 0; jj < len; jj++) { 2051146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (jj == ii) { 2052146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2053146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event neighbor = mSelectedEvents.get(jj); 2055146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborPosition = neighbor.getColumn(); 2056146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborPosition == position - 1) { 2057146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = neighbor; 2058146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborPosition == position + 1) { 2059146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = neighbor; 2060146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2061146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2062146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2063146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (startEvent != null) { 2064146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = startEvent; 2065146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2066146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = maxPositionEvent; 2067146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2068146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2069146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2070c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa private RectF drawAllDayEventRect(Event event, Canvas canvas, Paint p, Paint eventTextPaint) { 2071146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If this event is selected, then use the selection color 2072146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == event) { 2073146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 2074146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 2075146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setColor(mSelectionColor); 2076146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project eventTextPaint.setColor(mSelectedEventTextColor); 2077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2078146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use the normal color for all-day events 2079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setColor(event.color); 2080146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project eventTextPaint.setColor(mEventTextColor); 2081146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2082146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2083146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project RectF rf = mRectF; 2084146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rf.top = event.top; 2085146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rf.bottom = event.bottom; 2086146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rf.left = event.left; 2087146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rf.right = event.right; 20883eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawRect(rf, p); 2089146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2090146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rf.left += 2; 2091146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rf.right -= 2; 2092146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return rf; 2093146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2094146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2095146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawEvents(int date, int left, int top, Canvas canvas, Paint p) { 2096146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint eventTextPaint = mEventTextPaint; 2097146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellWidth = mCellWidth; 2098146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellHeight = mCellHeight; 2099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use the selected hour as the selection region 2101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect selectionArea = mRect; 2102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.top = top + mSelectionHour * (cellHeight + HOUR_GAP); 2103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.bottom = selectionArea.top + cellHeight; 2104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.left = left; 2105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.right = selectionArea.left + cellWidth; 2106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ArrayList<Event> events = mEvents; 2108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 2109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project EventGeometry geometry = mEventGeometry; 2110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 2112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 2113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!geometry.computeEventRect(date, left, top, cellWidth, event)) { 2114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (date == mSelectionDay && !mSelectionAllDay && mComputeSelectedEvents 2118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && geometry.eventIntersectsSelection(event, selectionArea)) { 2119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 2120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project RectF rf = drawEventRect(event, canvas, p, eventTextPaint); 21239c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan setupTextRect(rf); 2124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawEventText(event, rf, canvas, eventTextPaint, NORMAL_TEXT_TOP_MARGIN); 2125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (date == mSelectionDay && !mSelectionAllDay && isFocused() 2128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && mSelectionMode != SELECTION_HIDDEN) { 2129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeNeighbors(); 2130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 2131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project RectF rf = drawEventRect(mSelectedEvent, canvas, p, eventTextPaint); 21329c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan setupTextRect(rf); 2133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawEventText(mSelectedEvent, rf, canvas, eventTextPaint, NORMAL_TEXT_TOP_MARGIN); 2134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Computes the "nearest" neighbor event in four directions (left, right, 2139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // up, down) for each of the events in the mSelectedEvents array. 2140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeNeighbors() { 2141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 2142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len == 0 || mSelectedEvent != null) { 2143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear all the links 2147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = null; 2150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = null; 2151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = null; 2152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = null; 2153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event startEvent = mSelectedEvents.get(0); 2156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startEventDistance1 = 100000; // any large number 2157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startEventDistance2 = 100000; // any large number 2158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevLocation = FROM_NONE; 2159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevTop; 2160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevBottom; 2161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevLeft; 2162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevRight; 2163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevCenter = 0; 2164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect box = getCurrentSelectionPosition(); 2165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPrevSelectedEvent != null) { 2166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = (int) mPrevSelectedEvent.top; 2167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = (int) mPrevSelectedEvent.bottom; 2168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = (int) mPrevSelectedEvent.left; 2169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = (int) mPrevSelectedEvent.right; 2170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check if the previously selected event intersects the previous 2171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // selection box. (The previously selected event may be from a 2172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // much older selection box.) 2173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevTop >= mPrevBox.bottom || prevBottom <= mPrevBox.top 2174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || prevRight <= mPrevBox.left || prevLeft >= mPrevBox.right) { 2175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 2176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 2177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 2178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = mPrevBox.left; 2179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = mPrevBox.right; 2180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Clip the top and bottom to the previous selection box. 2182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevTop < mPrevBox.top) { 2183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 2184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevBottom > mPrevBox.bottom) { 2186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 2187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Just use the previously drawn selection box 2191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 2192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 2193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = mPrevBox.left; 2194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = mPrevBox.right; 2195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out where we came from and compute the center of that area. 2198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevLeft >= box.right) { 2199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was to the right of us. 2200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_RIGHT; 2201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevTop + prevBottom) / 2; 2202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevRight <= box.left) { 2203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was to the left of us. 2204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_LEFT; 2205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevTop + prevBottom) / 2; 2206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevBottom <= box.top) { 2207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was above us. 2208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_ABOVE; 2209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevLeft + prevRight) / 2; 2210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevTop >= box.bottom) { 2211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was below us. 2212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_BELOW; 2213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevLeft + prevRight) / 2; 2214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each event in the selected event list "mSelectedEvents", search 2217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // all the other events in that list for the nearest neighbor in 4 2218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // directions. 2219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2221146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startTime = ev.startTime; 2223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endTime = ev.endTime; 2224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int left = (int) ev.left; 2225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int right = (int) ev.right; 2226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int top = (int) ev.top; 2227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (top < box.top) { 2228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project top = box.top; 2229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int bottom = (int) ev.bottom; 2231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom > box.bottom) { 2232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project bottom = box.bottom; 2233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (false) { 2235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL 2236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 2237ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (DateFormat.is24HourFormat(mContext)) { 2238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags |= DateUtils.FORMAT_24HOUR; 2239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2240ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan String timeRange = DateUtils.formatDateRange(mContext, 2241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.startMillis, ev.endMillis, flags); 2242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Log.i("Cal", "left: " + left + " right: " + right + " top: " + top 2243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project + " bottom: " + bottom + " ev: " + timeRange + " " + ev.title); 2244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int upDistanceMin = 10000; // any large number 2246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int downDistanceMin = 10000; // any large number 2247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int leftDistanceMin = 10000; // any large number 2248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int rightDistanceMin = 10000; // any large number 2249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event upEvent = null; 2250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event downEvent = null; 2251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event leftEvent = null; 2252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event rightEvent = null; 2253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the starting event closest to the previously selected event, 2255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // if any. distance1 takes precedence over distance2. 2256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance1 = 0; 2257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance2 = 0; 2258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevLocation == FROM_ABOVE) { 2259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (left >= prevCenter) { 2260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = left - prevCenter; 2261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (right <= prevCenter) { 2262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - right; 2263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = top - prevBottom; 2265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_BELOW) { 2266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (left >= prevCenter) { 2267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = left - prevCenter; 2268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (right <= prevCenter) { 2269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - right; 2270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = prevTop - bottom; 2272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_LEFT) { 2273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom <= prevCenter) { 2274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - bottom; 2275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (top >= prevCenter) { 2276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = top - prevCenter; 2277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = left - prevRight; 2279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_RIGHT) { 2280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom <= prevCenter) { 2281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - bottom; 2282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (top >= prevCenter) { 2283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = top - prevCenter; 2284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = prevLeft - right; 2286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance1 < startEventDistance1 2288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || (distance1 == startEventDistance1 && distance2 < startEventDistance2)) { 2289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEvent = ev; 2290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEventDistance1 = distance1; 2291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEventDistance2 = distance2; 2292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each neighbor, figure out if it is above or below or left 2295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // or right of me and compute the distance. 2296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int jj = 0; jj < len; jj++) { 2297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (jj == ii) { 2298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event neighbor = mSelectedEvents.get(jj); 2301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborLeft = (int) neighbor.left; 2302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborRight = (int) neighbor.right; 2303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighbor.endTime <= startTime) { 2304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely above me. 2305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we overlap the same column, then compute the distance. 2306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft < right && neighborRight > left) { 2307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = startTime - neighbor.endTime; 2308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < upDistanceMin) { 2309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upDistanceMin = distance; 2310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upEvent = neighbor; 2311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == upDistanceMin) { 2312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (left + right) / 2; 2313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = 0; 2314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentLeft = (int) upEvent.left; 2315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentRight = (int) upEvent.right; 2316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (currentRight <= center) { 2317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = center - currentRight; 2318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (currentLeft >= center) { 2319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = currentLeft - center; 2320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = 0; 2323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborRight <= center) { 2324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = center - neighborRight; 2325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborLeft >= center) { 2326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = neighborLeft - center; 2327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upDistanceMin = distance; 2330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upEvent = neighbor; 2331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighbor.startTime >= endTime) { 2335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely below me. 2336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we overlap the same column, then compute the distance. 2337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft < right && neighborRight > left) { 2338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = neighbor.startTime - endTime; 2339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < downDistanceMin) { 2340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downDistanceMin = distance; 2341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downEvent = neighbor; 2342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == downDistanceMin) { 2343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (left + right) / 2; 2344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = 0; 2345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentLeft = (int) downEvent.left; 2346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentRight = (int) downEvent.right; 2347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (currentRight <= center) { 2348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = center - currentRight; 2349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (currentLeft >= center) { 2350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = currentLeft - center; 2351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = 0; 2354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborRight <= center) { 2355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = center - neighborRight; 2356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborLeft >= center) { 2357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = neighborLeft - center; 2358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downDistanceMin = distance; 2361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downEvent = neighbor; 2362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft >= right) { 2368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely to the right of me. 2369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Take the closest neighbor in the y direction. 2370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (top + bottom) / 2; 2371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = 0; 2372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborBottom = (int) neighbor.bottom; 2373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborTop = (int) neighbor.top; 2374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborBottom <= center) { 2375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = center - neighborBottom; 2376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborTop >= center) { 2377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = neighborTop - center; 2378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < rightDistanceMin) { 2380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightDistanceMin = distance; 2381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightEvent = neighbor; 2382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == rightDistanceMin) { 2383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the closest in the x direction 2384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = neighborLeft - right; 2385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = (int) rightEvent.left - right; 2386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightDistanceMin = distance; 2388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightEvent = neighbor; 2389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborRight <= left) { 2392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely to the left of me. 2393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Take the closest neighbor in the y direction. 2394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (top + bottom) / 2; 2395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = 0; 2396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborBottom = (int) neighbor.bottom; 2397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborTop = (int) neighbor.top; 2398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborBottom <= center) { 2399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = center - neighborBottom; 2400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborTop >= center) { 2401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = neighborTop - center; 2402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < leftDistanceMin) { 2404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftDistanceMin = distance; 2405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftEvent = neighbor; 2406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == leftDistanceMin) { 2407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the closest in the x direction 2408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = left - neighborRight; 2409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = left - (int) leftEvent.right; 2410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftDistanceMin = distance; 2412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftEvent = neighbor; 2413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = upEvent; 2418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = downEvent; 2419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = leftEvent; 2420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = rightEvent; 2421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = startEvent; 2423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private RectF drawEventRect(Event event, Canvas canvas, Paint p, Paint eventTextPaint) { 242611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw the Event Rect 24273eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan RectF rf = mRectF; 242811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.top = event.top + EVENT_RECT_TOP_MARGIN; 242911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.bottom = event.bottom - EVENT_RECT_BOTTOM_MARGIN; 243011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.left = event.left + EVENT_RECT_LEFT_MARGIN; 243111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.right = event.right - EVENT_RECT_RIGHT_MARGIN; 2432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 243311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // TEMP behavior 243411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setAntiAlias(false); 2435c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setColor(EVENT_OUTLINE_COLOR); 2436c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setStrokeWidth(2); 243711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setStyle(Style.STROKE); 243811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan canvas.drawRect(rf, p); 2439c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik rf.top++; 2440c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik rf.left ++; 2441c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik rf.right--; 2442c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik rf.bottom--; 244311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan int color = 0xAAFFFFFF; 244411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan int eventTextColor = mEventTextColor; 2445e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 2446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If this event is selected, then use the selection color 2447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == event) { 2448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_PRESSED) { 2449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 2450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 2451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // box = mBoxPressed; 245211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan color = mPressedColor; // FIXME:pressed 245311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan eventTextColor = mSelectedEventTextColor; 2454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionMode == SELECTION_SELECTED) { 2455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 2456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 2457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // box = mBoxSelected; 245811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan color = mSelectionColor; 245911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan eventTextColor = mSelectedEventTextColor; 2460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionMode == SELECTION_LONGPRESS) { 2461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // box = mBoxLongPressed; 246211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan color = mPressedColor; // FIXME: longpressed (maybe -- this doesn't seem to work) 246311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan eventTextColor = mSelectedEventTextColor; 2464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 246711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setColor(color); 246811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setStyle(Style.FILL); 246911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan eventTextPaint.setColor(eventTextColor); 247011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan canvas.drawRect(rf, p); 247111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan 247211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw cal color square border 247311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // TODO clean up once design is final 247411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.top = event.top - 2; 247511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.left = event.left - 3; 24769c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.bottom = rf.top + CALENDAR_COLOR_SQUARE_SIZE + 1; 24779c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.right = rf.left + CALENDAR_COLOR_SQUARE_SIZE + 1; 247811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setColor(0xFFFFFFFF); 24799c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan p.setStyle(Style.FILL); 248011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan canvas.drawRect(rf, p); 24818af2529989a9b10a0bb84736695c22fc02a17a4aThe Android Open Source Project 248211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw cal color 248311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.top++; 248411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.left++; 24859c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.bottom--; 24869c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan rf.right--; 248711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setColor(event.color); 248811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setStyle(Style.FILL); 24893eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawRect(rf, p); 2490e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 249111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan boolean declined = (event.selfAttendeeStatus == Attendees.ATTENDEE_STATUS_DECLINED); 249211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan if (declined) { 249311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan boolean aa = p.isAntiAlias(); 249411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan if (!aa) { 249511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setAntiAlias(true); 249611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan } 249711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Temp behavior 249811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setColor(0x88FFFFFF); 249911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan canvas.drawLine(rf.right, rf.top, rf.left, rf.bottom, p); 250011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan if (!aa) { 250111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setAntiAlias(false); 250211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan } 250311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan } 250411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan 25053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Setup rect for drawEventText which follows 250611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.top = event.top + EVENT_RECT_TOP_MARGIN; 250711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.bottom = event.bottom - EVENT_RECT_BOTTOM_MARGIN; 250811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.left = event.left + EVENT_RECT_LEFT_MARGIN; 250911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan rf.right = event.right - EVENT_RECT_RIGHT_MARGIN; 2510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return rf; 2511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2512146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 25130d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan private Pattern drawTextSanitizerFilter = Pattern.compile("[\t\n],"); 25140d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 25150d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // Sanitize a string before passing it to drawText or else we get little 25160d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // squares. For newlines and tabs before a comma, delete the character. 25170d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // Otherwise, just replace them with a space. 25180d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan private String drawTextSanitizer(String string) { 25190d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan Matcher m = drawTextSanitizerFilter.matcher(string); 25200d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan string = m.replaceAll(",").replace('\n', ' ').replace('\n', ' '); 25210d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan return string; 25220d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan } 25230d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 2524146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawEventText(Event event, RectF rf, Canvas canvas, Paint p, int topMargin) { 2525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!mDrawTextInEventRect) { 2526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float width = rf.right - rf.left; 2530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float height = rf.bottom - rf.top; 2531c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(true); 2532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Leave one pixel extra space between lines 2534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int lineHeight = mEventTextHeight + 1; 2535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the rectangle is too small for text, then return 2537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (width < MIN_CELL_WIDTH_FOR_TEXT || height <= lineHeight) { 2538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Truncate the event title to a known (large enough) limit 2542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String text = event.getTitleAndLocation(); 25430d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 25440d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan text = drawTextSanitizer(text); 25450d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 2546146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = text.length(); 2547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len > MAX_EVENT_TEXT_LEN) { 2548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = text.substring(0, MAX_EVENT_TEXT_LEN); 2549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project len = MAX_EVENT_TEXT_LEN; 2550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out how much space the event title will take, and create a 2553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // String fragment that will fit in the rectangle. Use multiple lines, 2554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // if available. 2555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.getTextWidths(text, mCharWidths); 2556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String fragment = text; 2557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float top = rf.top + mEventTextAscent + topMargin; 2558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int start = 0; 2559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Leave one pixel extra space at the bottom 2561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project while (start < len && height >= (lineHeight + 1)) { 2562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean lastLine = (height < 2 * lineHeight + 1); 2563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Skip leading spaces at the beginning of each line 2564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project do { 2565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project char c = text.charAt(start); 2566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (c != ' ') break; 2567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project start += 1; 2568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } while (start < len); 2569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float sum = 0; 2571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int end = start; 2572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = start; ii < len; ii++) { 2573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project char c = text.charAt(ii); 2574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we found the end of a word, then remember the ending 2576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // position. 2577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (c == ' ') { 2578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project end = ii; 2579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project sum += mCharWidths[ii]; 2581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If adding this character would exceed the width and this 2582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // isn't the last line, then break the line at the previous 2583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // word. If there was no previous word, then break this word. 2584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (sum > width) { 2585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (end > start && !lastLine) { 2586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // There was a previous word on this line. 2587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project fragment = text.substring(start, end); 2588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project start = end; 2589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 2590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the only word and it is too long to fit on 2593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the line (or this is the last line), so take as many 2594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // characters of this word as will fit. 2595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project fragment = text.substring(start, ii); 2596146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project start = ii; 2597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 2598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If sum <= width, then we can fit the rest of the text on 2602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // this line. 2603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (sum <= width) { 2604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project fragment = text.substring(start, len); 2605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project start = len; 2606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.drawText(fragment, rf.left + 1, top, p); 2609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project top += lineHeight; 2611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project height -= lineHeight; 2612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void updateEventDetails() { 2616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null || mSelectionMode == SELECTION_HIDDEN 2617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || mSelectionMode == SELECTION_LONGPRESS) { 2618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 2619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2621666fc5e8ddbac15c951aad738bd818ee307eae42Erik if (mLastPopupEventID == mSelectedEvent.id) { 2622666fc5e8ddbac15c951aad738bd818ee307eae42Erik return; 2623666fc5e8ddbac15c951aad738bd818ee307eae42Erik } 2624666fc5e8ddbac15c951aad738bd818ee307eae42Erik 2625666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = mSelectedEvent.id; 2626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Remove any outstanding callbacks to dismiss the popup. 2628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getHandler().removeCallbacks(mDismissPopup); 2629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = mSelectedEvent; 2631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView titleView = (TextView) mPopupView.findViewById(R.id.event_title); 2632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project titleView.setText(event.title); 2633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ImageView imageView = (ImageView) mPopupView.findViewById(R.id.reminder_icon); 2635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView.setVisibility(event.hasAlarm ? View.VISIBLE : View.GONE); 2636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView = (ImageView) mPopupView.findViewById(R.id.repeat_icon); 2638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView.setVisibility(event.isRepeating ? View.VISIBLE : View.GONE); 2639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2640146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags; 2641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.allDay) { 2642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags = DateUtils.FORMAT_UTC | DateUtils.FORMAT_SHOW_DATE | 2643146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_ALL; 2644146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2645146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE 2646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_ALL 2647146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 2648146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2649ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (DateFormat.is24HourFormat(mContext)) { 2650146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags |= DateUtils.FORMAT_24HOUR; 2651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2652731f1cb808b7586b93615b408ab2636081fab0dcErik String timeRange = Utils.formatDateRange(mContext, 2653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startMillis, event.endMillis, flags); 2654146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView timeView = (TextView) mPopupView.findViewById(R.id.time); 2655146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project timeView.setText(timeRange); 2656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView whereView = (TextView) mPopupView.findViewById(R.id.where); 2658146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final boolean empty = TextUtils.isEmpty(event.location); 2659146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project whereView.setVisibility(empty ? View.GONE : View.VISIBLE); 2660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!empty) whereView.setText(event.location); 2661146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2662146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.showAtLocation(this, Gravity.BOTTOM | Gravity.LEFT, mHoursWidth, 5); 2663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project postDelayed(mDismissPopup, POPUP_DISMISS_DELAY); 2664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2665146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The following routines are called from the parent activity when certain 2667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // touch events occur. 26684484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doDown(MotionEvent ev) { 2669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_DOWN; 2670146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = 0; 2671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mOnFlingCalled = false; 2672146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getHandler().removeCallbacks(mContinueScroll); 2673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2674146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 26754484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doSingleTapUp(MotionEvent ev) { 2676d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (!mHandleActionUp) { 2677d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return; 2678d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2679d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int x = (int) ev.getX(); 2681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = (int) ev.getY(); 2682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectedDay = mSelectionDay; 2683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectedHour = mSelectionHour; 2684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2685146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean validPosition = setSelectionFromPosition(x, y); 2686146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!validPosition) { 268780bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan // return if the touch wasn't on an area of concern 2688146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2689146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2690146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 269180bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan mSelectionMode = SELECTION_SELECTED; 2692146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 2693146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 269480bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan if (mSelectedEvent != null) { 269580bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan // If the tap is on an event, launch the "View event" view 2696344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, mSelectedEvent.id, 2697344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mSelectedEvent.startMillis, mSelectedEvent.endMillis, (int) ev.getRawX(), 2698344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan (int) ev.getRawY()); 2699344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan } else if (selectedDay == mSelectionDay && selectedHour == mSelectionHour) { 2700344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan // If the tap is on an already selected hour slot, then create a new 2701344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan // event 2702344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 2703344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan getSelectedTimeInMillis(), 0, (int) ev.getRawX(), (int) ev.getRawY()); 2704344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan } else { 2705344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan Time startTime = new Time(mBaseDate); 2706344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.setJulianDay(mSelectionDay); 2707344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.hour = mSelectionHour; 2708344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.normalize(true /* ignore isDst */); 270983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 271083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time endTime = new Time(startTime); 271183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan endTime.hour++; 271283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 2713344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mController.sendEvent(this, EventType.GO_TO, startTime, endTime, -1, ViewType.CURRENT); 2714146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2715146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2716146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 27174484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doLongPress(MotionEvent ev) { 2718d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // Scale gesture in progress 2719d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mStartingSpanY != 0) { 2720d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return; 2721d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2722d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 272380bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan int x = (int) ev.getX(); 272480bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan int y = (int) ev.getY(); 272580bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan 272680bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan boolean validPosition = setSelectionFromPosition(x, y); 272780bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan if (!validPosition) { 272880bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan // return if the touch wasn't on an area of concern 272980bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan return; 273080bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan } 273180bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan 2732146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 2733146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 2734146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project performLongClick(); 2735146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2736146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 27374484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doScroll(MotionEvent e1, MotionEvent e2, float deltaX, float deltaY) { 2738146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use the distance from the current point to the initial touch instead 2739146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // of deltaX and deltaY to avoid accumulating floating-point rounding 2740146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // errors. Also, we don't need floats, we can use ints. 2741146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceX = (int) e1.getX() - (int) e2.getX(); 2742146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceY = (int) e1.getY() - (int) e2.getY(); 2743146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2744146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we haven't figured out the predominant scroll direction yet, 2745146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // then do it now. 2746146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mTouchMode == TOUCH_MODE_DOWN) { 2747146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int absDistanceX = Math.abs(distanceX); 2748146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int absDistanceY = Math.abs(distanceY); 2749146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrollStartY = mViewStartY; 2750146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPreviousDirection = 0; 2751146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2752146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the x distance is at least twice the y distance, then lock 2753146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the scroll horizontally. Otherwise scroll vertically. 2754146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (absDistanceX >= 2 * absDistanceY) { 2755146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_HSCROLL; 2756146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = distanceX; 2757146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initNextView(-mViewStartX); 2758146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2759146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_VSCROLL; 2760146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2761146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 2762146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We are already scrolling horizontally, so check if we 2763146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // changed the direction of scrolling so that the other week 2764146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // is now visible. 2765146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = distanceX; 2766146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distanceX != 0) { 2767146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int direction = (distanceX > 0) ? 1 : -1; 2768146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (direction != mPreviousDirection) { 2769146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The user has switched the direction of scrolling 2770146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // so re-init the next view 2771146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initNextView(-mViewStartX); 2772146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPreviousDirection = direction; 2773146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2774146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2775146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2776146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2777146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_VSCROLL) != 0) { 2778146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mScrollStartY + distanceY; 2779146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 2780146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 2781146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mViewStartY > mMaxViewStartY) { 2782146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mMaxViewStartY; 2783146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2784146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeFirstHour(); 2785146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2786146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2787146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = true; 2788146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2789146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode != SELECTION_HIDDEN) { 2790146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_HIDDEN; 2791146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2792146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 2793146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2794146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 27954484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 2796146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_INITIAL_STATE; 2797146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_HIDDEN; 2798146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mOnFlingCalled = true; 2799146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaX = (int) e2.getX() - (int) e1.getX(); 2800146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceX = Math.abs(deltaX); 2801146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaY = (int) e2.getY() - (int) e1.getY(); 2802146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceY = Math.abs(deltaY); 2803146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2804146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((distanceX >= HORIZONTAL_SCROLL_THRESHOLD) && (distanceX > distanceY)) { 280511638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // initNextView(deltaX); 280611638ad4fb56b978770aebe75deac7a0e6ac60d2Erik 280711638ad4fb56b978770aebe75deac7a0e6ac60d2Erik switchViews(mViewStartX > 0, mViewStartX, mViewWidth); 280811638ad4fb56b978770aebe75deac7a0e6ac60d2Erik DayView view = (DayView) mViewSwitcher.getCurrentView(); 280983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 281083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time end = new Time(view.mBaseDate); 28111f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan end.monthDay += mNumDays; 28121f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan end.normalize(true); 28133458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan mController 2814487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan .sendEvent(this, EventType.GO_TO, view.mBaseDate, end, -1, ViewType.CURRENT); 281583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 2816146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = 0; 2817146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2818146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2819146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Continue scrolling vertically 2821146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mContinueScroll.init((int) velocityY / 20); 2822146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project post(mContinueScroll); 2823146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2824146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2825146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean initNextView(int deltaX) { 2826146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Change the view to the previous day or week 2827d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getNextView(); 2828146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time date = view.mBaseDate; 2829146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.set(mBaseDate); 2830146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean switchForward; 2831146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (deltaX > 0) { 2832146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay -= mNumDays; 2833146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = mSelectionDay - mNumDays; 2834146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchForward = false; 2835146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2836146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay += mNumDays; 2837146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = mSelectionDay + mNumDays; 2838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchForward = true; 2839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.normalize(true /* ignore isDst */); 2841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initView(view); 2842ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan view.layout(getLeft(), getTop(), getRight(), getBottom()); 2843146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.reloadEvents(); 2844146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return switchForward; 2845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2847d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 2848d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public boolean onScaleBegin(ScaleGestureDetector detector) { 2849d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = false; 2850d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float gestureCenterInPixels = detector.getFocusY() - DAY_HEADER_HEIGHT - mAllDayHeight; 2851d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) / (mCellHeight + DAY_GAP); 2852d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2853d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = Math.max(MIN_Y_SPAN, Math.abs(detector.getCurrentSpanY())); 2854d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = mCellHeight; 2855d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2856d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 2857d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float ViewStartHour = mViewStartY / (float) (mCellHeight + DAY_GAP); 2858d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.d(TAG, "mGestureCenterHour:" + mGestureCenterHour + "\tViewStartHour: " 2859d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + ViewStartHour + "\tmViewStartY:" + mViewStartY + "\tmCellHeight:" 2860d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + mCellHeight); 2861d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2862d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2863d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 2864d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2865d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2866d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 2867d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public boolean onScale(ScaleGestureDetector detector) { 2868d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float spanY = Math.abs(detector.getCurrentSpanY()); 2869d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2870d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = (int) (mCellHeightBeforeScaleGesture * spanY / mStartingSpanY); 2871d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2872d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight < mMinCellHeight) { 2873d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // If mStartingSpanY is too small, even a small increase in the 2874d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // gesture can bump the mCellHeight beyond MAX_CELL_HEIGHT 2875d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = Math.max(MIN_Y_SPAN, spanY); 2876d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = mMinCellHeight; 2877d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = mMinCellHeight; 2878d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } else if (mCellHeight > MAX_CELL_HEIGHT) { 2879d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = spanY; 2880d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = MAX_CELL_HEIGHT; 2881d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = MAX_CELL_HEIGHT; 2882d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2883d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2884d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan int gestureCenterInPixels = (int) detector.getFocusY() - DAY_HEADER_HEIGHT - mAllDayHeight; 2885d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = (int) (mGestureCenterHour * (mCellHeight + DAY_GAP)) - gestureCenterInPixels; 2886d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mMaxViewStartY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP) - mGridAreaHeight; 2887d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2888d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 2889d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float ViewStartHour = mViewStartY / (float) (mCellHeight + DAY_GAP); 2890d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.d(TAG, " mGestureCenterHour:" + mGestureCenterHour + "\tViewStartHour: " 2891d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + ViewStartHour + "\tmViewStartY:" + mViewStartY + "\tmCellHeight:" 2892d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + mCellHeight + " SpanY:" + detector.getCurrentSpanY()); 2893d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2894d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2895d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mViewStartY < 0) { 2896d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = 0; 2897d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) 2898d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan / (float) (mCellHeight + DAY_GAP); 2899d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } else if (mViewStartY > mMaxViewStartY) { 2900d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = mMaxViewStartY; 2901d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) 2902d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan / (float) (mCellHeight + DAY_GAP); 2903d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2904d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan computeFirstHour(); 2905d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2906d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mRemeasure = true; 2907d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan invalidate(); 2908d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 2909d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2910d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2911d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 2912d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public void onScaleEnd(ScaleGestureDetector detector) { 2913d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = 0; 2914d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2915d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2916146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 2917146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onTouchEvent(MotionEvent ev) { 2918146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int action = ev.getAction(); 2919146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2920d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mScaleGestureDetector.onTouchEvent(ev); 2921d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mScaleGestureDetector.isInProgress()) { 2922d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 2923d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2924d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2925146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (action) { 2926146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case MotionEvent.ACTION_DOWN: 2927d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) Log.e(TAG, "ACTION_DOWN"); 2928d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = true; 2929ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector.onTouchEvent(ev); 2930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 2931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2932146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case MotionEvent.ACTION_MOVE: 2933d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) Log.e(TAG, "ACTION_MOVE"); 2934ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector.onTouchEvent(ev); 2935146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 2936146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2937146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case MotionEvent.ACTION_UP: 2938d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) Log.e(TAG, "ACTION_UP " + mHandleActionUp); 2939ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector.onTouchEvent(ev); 2940d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (!mHandleActionUp) { 2941d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = true; 2942d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 2943d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2944146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mOnFlingCalled) { 2945146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 2946146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2947146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 2948146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_INITIAL_STATE; 2949146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (Math.abs(mViewStartX) > HORIZONTAL_SCROLL_THRESHOLD) { 2950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The user has gone beyond the threshold so switch views 2951ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan switchViews(mViewStartX > 0, mViewStartX, mViewWidth); 29527abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project mViewStartX = 0; 29537abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project return true; 2954146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Not beyond the threshold so invalidate which will cause 2956146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the view to snap back. Also call recalc() to ensure 2957146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // that we have the correct starting date and title. 2958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 2959146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 29607abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project mViewStartX = 0; 2961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2964146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we were scrolling, then reset the selected hour so that it 2965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // is visible. 2966146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mScrolling) { 2967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 2968146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project resetSelectedHour(); 2969146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 2970146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2971146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 2972146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2973146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This case isn't expected to happen. 2974146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case MotionEvent.ACTION_CANCEL: 2975d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) Log.e(TAG, "ACTION_CANCEL"); 2976ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector.onTouchEvent(ev); 2977146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 2978146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project resetSelectedHour(); 2979146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 2980146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2981146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project default: 2982d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) Log.e(TAG, "Not MotionEvent"); 2983ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (mGestureDetector.onTouchEvent(ev)) { 2984146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 2985146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2986146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onTouchEvent(ev); 2987146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2988146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2990146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { 2991146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project MenuItem item; 2992146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the trackball is held down, then the context menu pops up and 2994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // we never get onKeyUp() for the long-press. So check for it here 2995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // and change the selection to the long-press state. 2996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode != SELECTION_LONGPRESS) { 2997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 2998146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 2999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3000146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3001e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan final long startMillis = getSelectedTimeInMillis(); 3002146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags = DateUtils.FORMAT_SHOW_TIME 3003146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT 3004146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_SHOW_WEEKDAY; 3005ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan final String title = DateUtils.formatDateTime(mContext, startMillis, flags); 3006146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project menu.setHeaderTitle(title); 3007e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3008146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numSelectedEvents = mSelectedEvents.size(); 3009146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 1) { 3010146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Day view. 3011146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3012146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is a selected event, then allow it to be viewed and 3013146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // edited. 3014146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (numSelectedEvents >= 1) { 30154484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_VIEW, 0, R.string.event_view); 3016146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3017146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_info_details); 3018146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3019ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan int accessLevel = getEventAccessLevel(mContext, mSelectedEvent); 3020a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel == ACCESS_LEVEL_EDIT) { 30214484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_EDIT, 0, R.string.event_edit); 3022146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3023146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_edit); 3024146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('e'); 3025a505627659f6bfba8869eac8089f7030f2d0d92cErik } 3026146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3027a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel >= ACCESS_LEVEL_DELETE) { 30284484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_DELETE, 0, R.string.event_delete); 3029146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3030146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_delete); 3031146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3032146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 30334484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 3034146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3035146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_add); 3036146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('n'); 3037146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3038146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Otherwise, if the user long-pressed on a blank hour, allow 3039146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // them to create an event. They can also do this by tapping. 30404484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 3041146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3042146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_add); 3043146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('n'); 3044146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3045146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3046146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Week view. 3047e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3048146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is a selected event, then allow it to be viewed and 3049146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // edited. 3050146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (numSelectedEvents >= 1) { 30514484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_VIEW, 0, R.string.event_view); 3052146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3053146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_info_details); 3054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3055ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan int accessLevel = getEventAccessLevel(mContext, mSelectedEvent); 3056a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel == ACCESS_LEVEL_EDIT) { 30574484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_EDIT, 0, R.string.event_edit); 3058146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3059146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_edit); 3060146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('e'); 3061a505627659f6bfba8869eac8089f7030f2d0d92cErik } 3062146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3063a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel >= ACCESS_LEVEL_DELETE) { 30644484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_DELETE, 0, R.string.event_delete); 3065146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3066146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_delete); 3067146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 30684484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan } 3069146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 30704484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 30714484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 30724484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_add); 30734484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('n'); 3074146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 30754484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_DAY, 0, R.string.show_day_view); 30764484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 30774484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_day); 30784484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('d'); 3079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 30804484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_AGENDA, 0, R.string.show_agenda_view); 30814484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 30824484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_agenda); 30834484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('a'); 3084146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3085146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3086146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3087146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3088146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3089146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private class ContextMenuHandler implements MenuItem.OnMenuItemClickListener { 3090146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onMenuItemClick(MenuItem item) { 3091146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (item.getItemId()) { 30924484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_VIEW: { 3093146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 30949e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, 30959e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.id, mSelectedEvent.startMillis, 30969e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.endMillis, 0, 0); 3097146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3098146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31004484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_EDIT: { 3101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 31029e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.EDIT_EVENT, 31039e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.id, mSelectedEvent.startMillis, 31049e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.endMillis, 0, 0); 3105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31084484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_DAY: { 3109487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mController.sendEvent(this, EventType.GO_TO, getSelectedTime(), null, -1, 31109e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan ViewType.DAY); 3111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31134484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_AGENDA: { 3114487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mController.sendEvent(this, EventType.GO_TO, getSelectedTime(), null, -1, 31159e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan ViewType.AGENDA); 3116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31184484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_CREATE: { 3119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 3120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 31219e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 31229e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan startMillis, endMillis, 0, 0); 3123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31254484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_DELETE: { 3126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 3127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 3128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long begin = selectedEvent.startMillis; 3129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long end = selectedEvent.endMillis; 3130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long id = selectedEvent.id; 31319e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.DELETE_EVENT, id, begin, 31329e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan end, 0, 0); 3133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project default: { 3137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return false; 3138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 3141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3144a505627659f6bfba8869eac8089f7030f2d0d92cErik private static int getEventAccessLevel(Context context, Event e) { 3145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ContentResolver cr = context.getContentResolver(); 3146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int visibility = Calendars.NO_ACCESS; 3148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Get the calendar id for this event 3150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Cursor cursor = cr.query(ContentUris.withAppendedId(Events.CONTENT_URI, e.id), 3151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project new String[] { Events.CALENDAR_ID }, 3152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* selection */, 3153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* selectionArgs */, 3154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* sort */); 3155e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3156e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan if (cursor == null) { 3157a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 3158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3159e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3160e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan if (cursor.getCount() == 0) { 3161e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan cursor.close(); 3162a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 3163e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan } 3164e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.moveToFirst(); 3166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long calId = cursor.getLong(0); 3167697bd6a8cec36cc75c72603674e57e4c6fe42dbfKen Shirriff cursor.close(); 3168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Uri uri = Calendars.CONTENT_URI; 3170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String where = String.format(CALENDARS_WHERE, calId); 3171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor = cr.query(uri, CALENDARS_PROJECTION, where, null, null); 3172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 31736d34cec523930368976bc8d358d0a6de1da3462cMichael Chan String calendarOwnerAccount = null; 3174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (cursor != null) { 3175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.moveToFirst(); 3176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project visibility = cursor.getInt(CALENDARS_INDEX_ACCESS_LEVEL); 31776d34cec523930368976bc8d358d0a6de1da3462cMichael Chan calendarOwnerAccount = cursor.getString(CALENDARS_INDEX_OWNER_ACCOUNT); 3178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.close(); 3179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3180e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 31816d34cec523930368976bc8d358d0a6de1da3462cMichael Chan if (visibility < Calendars.CONTRIBUTOR_ACCESS) { 3182a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 31836d34cec523930368976bc8d358d0a6de1da3462cMichael Chan } 3184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 31856d34cec523930368976bc8d358d0a6de1da3462cMichael Chan if (e.guestsCanModify) { 3186a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_EDIT; 3187a505627659f6bfba8869eac8089f7030f2d0d92cErik } 3188a505627659f6bfba8869eac8089f7030f2d0d92cErik 3189a505627659f6bfba8869eac8089f7030f2d0d92cErik if (!TextUtils.isEmpty(calendarOwnerAccount) && 3190a505627659f6bfba8869eac8089f7030f2d0d92cErik calendarOwnerAccount.equalsIgnoreCase(e.organizer)) { 3191a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_EDIT; 3192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3194a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_DELETE; 3195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Sets mSelectionDay and mSelectionHour based on the (x,y) touch position. 3199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * If the touch position is not within the displayed grid, then this 3200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * method returns false. 3201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 3202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param x the x position of the touch 3203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param y the y position of the touch 3204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return true if the touch position is valid 3205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 3206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean setSelectionFromPosition(int x, int y) { 3207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (x < mHoursWidth) { 3208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return false; 3209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int day = (x - mHoursWidth) / (mCellWidth + DAY_GAP); 3212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (day >= mNumDays) { 3213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project day = mNumDays - 1; 3214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project day += mFirstJulianDay; 3216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int hour; 3217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (y < mFirstCell + mFirstHourOffset) { 3218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = true; 3219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project hour = (y - mFirstCell - mFirstHourOffset) / (mCellHeight + HOUR_GAP); 3221146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project hour += mFirstHour; 3222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = hour; 3223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = false; 3224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = day; 3226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project findSelectedEvent(x, y); 3227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", "setSelectionFromPosition( " + x + ", " + y + " ) day: " + day 3228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// + " hour: " + hour 3229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// + " mFirstCell: " + mFirstCell + " mFirstHourOffset: " + mFirstHourOffset); 3230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// if (mSelectedEvent != null) { 3231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", " num events: " + mSelectedEvents.size() + " event: " + mSelectedEvent.title); 3232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// for (Event ev : mSelectedEvents) { 3233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL 3234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 3235ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// String timeRange = formatDateRange(mContext, 3236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// ev.startMillis, ev.endMillis, flags); 3237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// 3238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", " " + timeRange + " " + ev.title); 3239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// } 3240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// } 3241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 3242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void findSelectedEvent(int x, int y) { 3245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int date = mSelectionDay; 3246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellWidth = mCellWidth; 3247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ArrayList<Event> events = mEvents; 3248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 3249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int left = mHoursWidth + (mSelectionDay - mFirstJulianDay) * (cellWidth + DAY_GAP); 3250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int top = 0; 3251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 3252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 3254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay) { 3255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float yDistance; 3256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float minYdistance = 10000.0f; // any large number 3257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event closestEvent = null; 3258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float drawHeight = mAllDayHeight; 32593eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int yOffset = DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 3260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 3261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 3262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!event.allDay) { 3263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.startDay <= mSelectionDay && event.endDay >= mSelectionDay) { 3267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float numRectangles = event.getMaxColumns(); 3268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float height = drawHeight / numRectangles; 3269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (height > MAX_ALLDAY_EVENT_HEIGHT) { 3270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project height = MAX_ALLDAY_EVENT_HEIGHT; 3271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float eventTop = yOffset + height * event.getColumn(); 3273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float eventBottom = eventTop + height; 3274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (eventTop < y && eventBottom > y) { 3275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the touch is inside the event rectangle, then 3276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // add the event. 3277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 3278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = event; 3279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Find the closest event 3282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (eventTop >= y) { 3283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project yDistance = eventTop - y; 3284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project yDistance = y - eventBottom; 3286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (yDistance < minYdistance) { 3288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project minYdistance = yDistance; 3289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = event; 3290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = closestEvent; 3295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Adjust y for the scrollable bitmap 3299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += mViewStartY - mFirstCell; 3300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use a region around (x,y) for the selection region 3302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect region = mRect; 3303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.left = x - 10; 3304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.right = x + 10; 3305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.top = y - 10; 3306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.bottom = y + 10; 3307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project EventGeometry geometry = mEventGeometry; 3309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 3311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 3312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the event rectangle. 3313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!geometry.computeEventRect(date, left, top, cellWidth, event)) { 3314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the event intersects the selection region, then add it to 3318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // mSelectedEvents. 3319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (geometry.eventIntersectsSelection(event, region)) { 3320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 3321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there are any events in the selected region, then assign the 3325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // closest one to mSelectedEvent. 3326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvents.size() > 0) { 3327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 3328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event closestEvent = null; 3329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float minDist = mViewWidth + mViewHeight; // some large distance 3330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int index = 0; index < len; index++) { 3331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(index); 3332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float dist = geometry.pointToEvent(x, y, ev); 3333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (dist < minDist) { 3334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project minDist = dist; 3335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = ev; 3336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = closestEvent; 3339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Keep the selected hour and day consistent with the selected 3341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event. They could be different if we touched on an empty hour 3342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // slot very close to an event in the previous hour slot. In 3343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // that case we will select the nearby event. 3344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startDay = mSelectedEvent.startDay; 3345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endDay = mSelectedEvent.endDay; 3346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionDay < startDay) { 3347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = startDay; 3348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionDay > endDay) { 3349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = endDay; 3350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startHour = mSelectedEvent.startTime / 60; 3353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endHour; 3354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent.startTime < mSelectedEvent.endTime) { 3355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endHour = (mSelectedEvent.endTime - 1) / 60; 3356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endHour = mSelectedEvent.endTime / 60; 3358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < startHour) { 3361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = startHour; 3362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionHour > endHour) { 3363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = endHour; 3364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Encapsulates the code to continue the scrolling after the 3369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // finger is lifted. Instead of stopping the scroll immediately, 3370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the scroll continues to "free spin" and gradually slows down. 3371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private class ContinueScroll implements Runnable { 3372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int mSignDeltaY; 3373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int mAbsDeltaY; 3374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float mFloatDeltaY; 3375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long mFreeSpinTime; 3376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final float FRICTION_COEF = 0.7F; 3377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final long FREE_SPIN_MILLIS = 180; 3378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int MAX_DELTA = 60; 3379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SCROLL_REPEAT_INTERVAL = 30; 3380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void init(int deltaY) { 3382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSignDeltaY = 0; 3383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (deltaY > 0) { 3384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSignDeltaY = 1; 3385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (deltaY < 0) { 3386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSignDeltaY = -1; 3387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = Math.abs(deltaY); 3389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Limit the maximum speed 3391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY > MAX_DELTA) { 3392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = MAX_DELTA; 3393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFloatDeltaY = mAbsDeltaY; 3395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFreeSpinTime = System.currentTimeMillis() + FREE_SPIN_MILLIS; 3396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", "init scroll: mAbsDeltaY: " + mAbsDeltaY 3397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// + " mViewStartY: " + mViewStartY); 3398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 3401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long time = System.currentTimeMillis(); 3402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Start out with a frictionless "free spin" 3404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (time > mFreeSpinTime) { 3405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the delta is small, then apply a fixed deceleration. 3406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Otherwise 3407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY <= 10) { 3408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY -= 2; 3409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFloatDeltaY *= FRICTION_COEF; 3411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = (int) mFloatDeltaY; 3412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY < 0) { 3415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = 0; 3416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSignDeltaY == 1) { 3420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY -= mAbsDeltaY; 3421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY += mAbsDeltaY; 3423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", " scroll: mAbsDeltaY: " + mAbsDeltaY 3425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// + " mViewStartY: " + mViewStartY); 3426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 3428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 3429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = 0; 3430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mViewStartY > mMaxViewStartY) { 3431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mMaxViewStartY; 3432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = 0; 3433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeFirstHour(); 3436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY > 0) { 3438146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project postDelayed(this, SCROLL_REPEAT_INTERVAL); 3439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Done scrolling. 3441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 3442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project resetSelectedHour(); 3443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3450bd0e834aea317236d574f8738fe11a51fdc87968Erik * Cleanup the pop-up and timers. 3451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 3452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void cleanup() { 3453146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against null-pointer exceptions 3454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPopup != null) { 3455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3457666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 3458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Handler handler = getHandler(); 3459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (handler != null) { 3460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project handler.removeCallbacks(mDismissPopup); 3461bd0e834aea317236d574f8738fe11a51fdc87968Erik handler.removeCallbacks(mUpdateCurrentTime); 3462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3463e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3464d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Utils.setSharedPreference(mContext, GeneralPreferences.KEY_DEFAULT_CELL_HEIGHT, 3465d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight); 3466d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 34677abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project // Turn off redraw 34687abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project mRemeasure = false; 3469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3471bd0e834aea317236d574f8738fe11a51fdc87968Erik /** 3472bd0e834aea317236d574f8738fe11a51fdc87968Erik * Restart the update timer 3473bd0e834aea317236d574f8738fe11a51fdc87968Erik */ 3474bd0e834aea317236d574f8738fe11a51fdc87968Erik public void restartCurrentTimeUpdates() { 3475bd0e834aea317236d574f8738fe11a51fdc87968Erik post(mUpdateCurrentTime); 3476bd0e834aea317236d574f8738fe11a51fdc87968Erik } 3477bd0e834aea317236d574f8738fe11a51fdc87968Erik 3478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override protected void onDetachedFromWindow() { 3479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cleanup(); 3480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project super.onDetachedFromWindow(); 3481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project class DismissPopup implements Runnable { 3484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 3485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against null-pointer exceptions 3486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPopup != null) { 3487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3491bd0e834aea317236d574f8738fe11a51fdc87968Erik 3492bd0e834aea317236d574f8738fe11a51fdc87968Erik class UpdateCurrentTime implements Runnable { 3493bd0e834aea317236d574f8738fe11a51fdc87968Erik public void run() { 3494bd0e834aea317236d574f8738fe11a51fdc87968Erik long currentTime = System.currentTimeMillis(); 3495bd0e834aea317236d574f8738fe11a51fdc87968Erik mCurrentTime.set(currentTime); 3496bd0e834aea317236d574f8738fe11a51fdc87968Erik //% causes update to occur on 5 minute marks (11:10, 11:15, 11:20, etc.) 3497bd0e834aea317236d574f8738fe11a51fdc87968Erik postDelayed(mUpdateCurrentTime, 3498bd0e834aea317236d574f8738fe11a51fdc87968Erik UPDATE_CURRENT_TIME_DELAY - (currentTime % UPDATE_CURRENT_TIME_DELAY)); 3499bd0e834aea317236d574f8738fe11a51fdc87968Erik mTodayJulianDay = Time.getJulianDay(currentTime, mCurrentTime.gmtoff); 3500bd0e834aea317236d574f8738fe11a51fdc87968Erik invalidate(); 3501bd0e834aea317236d574f8738fe11a51fdc87968Erik } 3502bd0e834aea317236d574f8738fe11a51fdc87968Erik } 3503ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3504ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener { 3505ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3506ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onSingleTapUp(MotionEvent ev) { 3507d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doSingleTapUp(ev); 3508ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3509ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3510ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3511ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3512ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public void onLongPress(MotionEvent ev) { 3513d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doLongPress(ev); 3514ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3515ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3516ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3517ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 3518d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doScroll(e1, e2, distanceX, distanceY); 3519ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3520ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3521ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3522ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3523ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 3524d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doFling(e1, e2, velocityX, velocityY); 3525ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3526ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3527ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3528ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3529ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onDown(MotionEvent ev) { 3530d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doDown(ev); 3531ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3532ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3533ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project} 3535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3536