DayView.java revision 000ba1109e2f4e527e9227fe341598ceeb3fbca6
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.Rect; 32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Typeface; 33c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawaimport android.graphics.drawable.Drawable; 34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.net.Uri; 35146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.os.Handler; 36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.provider.Calendar.Attendees; 37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.provider.Calendar.Calendars; 38146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.provider.Calendar.Events; 393e7015267340b09d142dfcd3ff8acda257711023Shachar Shemeshimport android.text.Layout.Alignment; 40f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chanimport android.text.StaticLayout; 413e7015267340b09d142dfcd3ff8acda257711023Shachar Shemeshimport android.text.TextPaint; 42f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chanimport 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 96146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mOnFlingCalled; 97666fc5e8ddbac15c951aad738bd818ee307eae42Erik /** 98666fc5e8ddbac15c951aad738bd818ee307eae42Erik * ID of the last event which was displayed with the toast popup. 99666fc5e8ddbac15c951aad738bd818ee307eae42Erik * 100666fc5e8ddbac15c951aad738bd818ee307eae42Erik * This is used to prevent popping up multiple quick views for the same event, especially 101666fc5e8ddbac15c951aad738bd818ee307eae42Erik * during calendar syncs. This becomes valid when an event is selected, either by default 102666fc5e8ddbac15c951aad738bd818ee307eae42Erik * on starting calendar or by scrolling to an event. It becomes invalid when the user 103666fc5e8ddbac15c951aad738bd818ee307eae42Erik * explicitly scrolls to an empty time slot, changes views, or deletes the event. 104666fc5e8ddbac15c951aad738bd818ee307eae42Erik */ 105666fc5e8ddbac15c951aad738bd818ee307eae42Erik private long mLastPopupEventID; 106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 107ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan protected Context mContext; 108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String[] CALENDARS_PROJECTION = new String[] { 110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Calendars._ID, // 0 111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Calendars.ACCESS_LEVEL, // 1 1126d34cec523930368976bc8d358d0a6de1da3462cMichael Chan Calendars.OWNER_ACCOUNT, // 2 113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int CALENDARS_INDEX_ACCESS_LEVEL = 1; 1156d34cec523930368976bc8d358d0a6de1da3462cMichael Chan private static final int CALENDARS_INDEX_OWNER_ACCOUNT = 2; 116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String CALENDARS_WHERE = Calendars._ID + "=%d"; 117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String[] ATTENDEES_PROJECTION = new String[] { 119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Attendees._ID, // 0 120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Attendees.ATTENDEE_RELATIONSHIP, // 1 121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int ATTENDEES_INDEX_RELATIONSHIP = 1; 123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=%d"; 124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_NONE = 0; 126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_ABOVE = 1; 127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_BELOW = 2; 128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_LEFT = 4; 129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_RIGHT = 8; 130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 131a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_NONE = 0; 132a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_DELETE = 1; 133a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_EDIT = 2; 134a505627659f6bfba8869eac8089f7030f2d0d92cErik 135d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan private static int mHorizontalSnapBackThreshold = 128; 136d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan private static int HORIZONTAL_FLING_THRESHOLD = 75; 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>(); 17908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private ArrayList<Event> mAllDayEvents = new ArrayList<Event>(); 18008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout[] mLayouts = null; 18108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout[] mAllDayLayouts = null; 182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionDay; // Julian day 183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionHour; 184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean mSelectionAllDay; 186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1873eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan /** Width of a day or non-conflicting event */ 188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mCellWidth; 189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pre-allocate these objects and re-use them 191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mRect = new Rect(); 192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mDestRect = new Rect(); 193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mPaint = new Paint(); 194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mEventTextPaint = new Paint(); 195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mSelectionPaint = new Paint(); 19602041687c35441e8a21cb763f1fc3a26525292efDavid Brown private float[] mLines; 197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 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 212000ba1109e2f4e527e9227fe341598ceeb3fbca6Michael Chan private static final float GRID_LINE_INNER_WIDTH = 1; 213000ba1109e2f4e527e9227fe341598ceeb3fbca6Michael Chan private static final float 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; 2181ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int MAX_ALLDAY_HEIGHT = 105; 219705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static int ALLDAY_TOP_MARGIN = 3; 220f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan private static int MAX_HEIGHT_OF_ONE_ALLDAY_EVENT = 34; 221e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int HOURS_LEFT_MARGIN = 2; 223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int HOURS_RIGHT_MARGIN = 4; 224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int HOURS_MARGIN = HOURS_LEFT_MARGIN + HOURS_RIGHT_MARGIN; 225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 226bd0e834aea317236d574f8738fe11a51fdc87968Erik private static int CURRENT_TIME_LINE_HEIGHT = 2; 227bd0e834aea317236d574f8738fe11a51fdc87968Erik private static int CURRENT_TIME_LINE_BORDER_WIDTH = 1; 2281ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static final int CURRENT_TIME_LINE_SIDE_BUFFER = 2; 229bd0e834aea317236d574f8738fe11a51fdc87968Erik 230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MINUTES_PER_HOUR = 60; 231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MINUTES_PER_DAY = MINUTES_PER_HOUR * 24; 232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_MINUTE = 60 * 1000; 233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_HOUR = (3600 * 1000); 234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_DAY = MILLIS_PER_HOUR * 24; 235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2363eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static final int DAY_HEADER_ALPHA = 0x26000000; 2373eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static final int DAY_HEADER_TODAY_ALPHA = 0x99000000; 23811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static float DAY_HEADER_ONE_DAY_LEFT_MARGIN = -12; 2393eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_ONE_DAY_RIGHT_MARGIN = 5; 2403eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_ONE_DAY_BOTTOM_MARGIN = 6; 2413eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_LEFT_MARGIN = 5; 2423eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_RIGHT_MARGIN = 7; 2433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_BOTTOM_MARGIN = 3; 2443eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_FONT_SIZE = 14; 2453eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DATE_HEADER_FONT_SIZE = 24; 2463eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float NORMAL_FONT_SIZE = 12; 2473eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float EVENT_TEXT_FONT_SIZE = 12; 2483eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float HOURS_FONT_SIZE = 12; 2493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float AMPM_FONT_SIZE = 9; 250705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static int MIN_CELL_WIDTH_FOR_TEXT = 27; 251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int MAX_EVENT_TEXT_LEN = 500; 252705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static float MIN_EVENT_HEIGHT = 15.0F; // in pixels 2531ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int CALENDAR_COLOR_SQUARE_SIZE = 10; 2541ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int CALENDAR_COLOR_SQUARE_V_OFFSET = -1; 2551ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int CALENDAR_COLOR_SQUARE_H_OFFSET = -3; 2561ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_RECT_TOP_MARGIN = -1; 2571ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_RECT_BOTTOM_MARGIN = -1; 2581ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_RECT_LEFT_MARGIN = -1; 2591ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_RECT_RIGHT_MARGIN = -1; 2601ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_TEXT_TOP_MARGIN = 2; 2611ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_TEXT_BOTTOM_MARGIN = 3; 2621ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_TEXT_LEFT_MARGIN = 11; 2631ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_TEXT_RIGHT_MARGIN = 4; 2641ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_TOP_MARGIN = EVENT_TEXT_TOP_MARGIN; 2651ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN = EVENT_TEXT_BOTTOM_MARGIN; 2661ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_LEFT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 2671ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_RIGHT_MARGIN = EVENT_TEXT_RIGHT_MARGIN; 268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mSelectionColor; 270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mPressedColor; 271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mSelectedEventTextColor; 272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mEventTextColor; 27364b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok private static int mWeek_saturdayColor; 27464b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok private static int mWeek_sundayColor; 275d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarDateBannerTextColor; 2763eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarAllDayBackground; 277d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarAmPmLabel; 2783eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarDateBannerBackground; 27911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// private static int mCalendarDateSelected; 2803eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarGridAreaBackground; 281ba902466b19b11d587468e354edc58e542707747Michael Chan private static int mCalendarGridAreaSelected; 282d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarGridLineHorizontalColor; 283d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarGridLineVerticalColor; 2843eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int mCalendarGridLineInnerHorizontalColor; 2853eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int mCalendarGridLineInnerVerticalColor; 2863eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private static int mCalendarHourBackground; 287d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarHourLabel; 28811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// private static int mCalendarHourSelected; 289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewStartX; 291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewStartY; 292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMaxViewStartY; 293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewHeight; 294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewWidth; 295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mGridAreaHeight; 296d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int mCellHeight = 0; // shared among all DayViews 297d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int mMinCellHeight = 32; 298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mScrollStartY; 299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mPreviousDirection; 300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 301d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** 302d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * Vertical distance or span between the two touch points at the start of a 303d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * scaling gesture 304d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan */ 305d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private float mStartingSpanY = 0; 306d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** Height of 1 hour in pixels at the start of a scaling gesture */ 307d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private int mCellHeightBeforeScaleGesture; 308d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** The hour at the center two touch points */ 309d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private float mGestureCenterHour = 0; 310d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** 311d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * Flag to decide whether to handle the up event. Cases where up events 312d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * should be ignored are 1) right after a scale gesture and 2) finger was 313d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * down before app launch 314d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan */ 315d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private boolean mHandleActionUp = true; 316d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mHoursTextHeight; 318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mAllDayHeight; 3193eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int DAY_HEADER_HEIGHT = 45; 320f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan /** 321f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan * Max of all day events in a given day in this view. 322f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan */ 323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMaxAllDayEvents; 324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected int mNumDays = 7; 326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mNumHours = 10; 3273eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 3283eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan /** Width of the time line (list of hours) to the left. */ 329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mHoursWidth; 330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mDateStrWidth; 331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstCell; 332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstHour = -1; 333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstHourOffset; 334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mHourStrs; 335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mDayStrs; 336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mDayStrs2Letter; 337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mIs24HourFormat; 338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ArrayList<Event> mSelectedEvents = new ArrayList<Event>(); 340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mComputeSelectedEvents; 341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Event mSelectedEvent; 342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Event mPrevSelectedEvent; 343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mPrevBox = new Rect(); 344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected final Resources mResources; 3453eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan protected final Drawable mCurrentTimeLine; 3463eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan protected final Drawable mTodayHeaderDrawable; 3471ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan protected final Drawable mEventBoxDrawable; 348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String mAmString; 349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String mPmString; 350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private DeleteEventHelper mDeleteEventHelper; 351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ContextMenuHandler mContextMenuHandler = new ContextMenuHandler(); 353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 354d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan ScaleGestureDetector mScaleGestureDetector; 355d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The initial state of the touch mode when we enter this view. 358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_INITIAL_STATE = 0; 360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates we just received the touch event and we are waiting to see if 363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * it is a tap or a scroll gesture. 364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_DOWN = 1; 366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates the touch gesture is a vertical scroll 369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_VSCROLL = 0x20; 371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates the touch gesture is a horizontal scroll 374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_HSCROLL = 0x40; 376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mTouchMode = TOUCH_MODE_INITIAL_STATE; 378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The selection modes are HIDDEN, PRESSED, SELECTED, and LONGPRESS. 381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_HIDDEN = 0; 383ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan private static final int SELECTION_PRESSED = 1; // D-pad down but not up yet 384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_SELECTED = 2; 385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_LONGPRESS = 3; 386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionMode = SELECTION_HIDDEN; 388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mScrolling = false; 390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 391ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private CalendarController mController; 392ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private ViewSwitcher mViewSwitcher; 393ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private GestureDetector mGestureDetector; 394705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 395d190418220467c02327dd9b3ae1eae238889720bMichael Chan public DayView(Context context, CalendarController controller, 39675d9b567e1fd3b9c6945cd0afe28781f5a19c6c8Michael Chan ViewSwitcher viewSwitcher, EventLoader eventLoader, int numDays) { 397ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan super(context); 398705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan if (mScale == 0) { 399705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan mScale = getContext().getResources().getDisplayMetrics().density; 400705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan if (mScale != 1) { 401705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan SINGLE_ALLDAY_HEIGHT *= mScale; 402705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan ALLDAY_TOP_MARGIN *= mScale; 403f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan MAX_HEIGHT_OF_ONE_ALLDAY_EVENT *= mScale; 404705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 405705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan NORMAL_FONT_SIZE *= mScale; 406705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan EVENT_TEXT_FONT_SIZE *= mScale; 407705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan HOURS_FONT_SIZE *= mScale; 408705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan AMPM_FONT_SIZE *= mScale; 409705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan MIN_CELL_WIDTH_FOR_TEXT *= mScale; 410705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan MIN_EVENT_HEIGHT *= mScale; 411705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 412d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan HORIZONTAL_FLING_THRESHOLD *= mScale; 413e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 414bd0e834aea317236d574f8738fe11a51fdc87968Erik CURRENT_TIME_LINE_HEIGHT *= mScale; 415bd0e834aea317236d574f8738fe11a51fdc87968Erik CURRENT_TIME_LINE_BORDER_WIDTH *= mScale; 416bd0e834aea317236d574f8738fe11a51fdc87968Erik 417d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan MIN_Y_SPAN *= mScale; 418d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan MAX_CELL_HEIGHT *= mScale; 419697157470a6f0d8e7b806af9b4fb7fbe0bccae87Erik DEFAULT_CELL_HEIGHT *= mScale; 4203eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_HEIGHT *= mScale; 4213eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_LEFT_MARGIN *= mScale; 4223eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_RIGHT_MARGIN *= mScale; 4233eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_BOTTOM_MARGIN *= mScale; 4243eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_LEFT_MARGIN *= mScale; 4253eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_RIGHT_MARGIN *= mScale; 4263eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_BOTTOM_MARGIN *= mScale; 4273eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_FONT_SIZE *= mScale; 4283eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DATE_HEADER_FONT_SIZE *= mScale; 4293eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan CALENDAR_COLOR_SQUARE_SIZE *= mScale; 4303eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_TOP_MARGIN *= mScale; 4313eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_BOTTOM_MARGIN *= mScale; 4323eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_LEFT_MARGIN *= mScale; 4333eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan EVENT_TEXT_RIGHT_MARGIN *= mScale; 4349c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_TOP_MARGIN *= mScale; 4359c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN *= mScale; 4369c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_LEFT_MARGIN *= mScale; 4379c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan EVENT_ALL_DAY_TEXT_RIGHT_MARGIN *= mScale; 43811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_TOP_MARGIN *= mScale; 43911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_BOTTOM_MARGIN *= mScale; 44011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_LEFT_MARGIN *= mScale; 44111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_RIGHT_MARGIN *= mScale; 442705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan } 443705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan } 444705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 445ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mResources = context.getResources(); 4463eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine = mResources.getDrawable(R.drawable.timeline_week_holo_light); 4473eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable = mResources.getDrawable(R.drawable.today_blue_week_holo_light); 4481ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mEventBoxDrawable = mResources.getDrawable(R.drawable.panel_month_event_holo_light); 449ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mEventLoader = eventLoader; 450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry = new EventGeometry(); 451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setMinEventHeight(MIN_EVENT_HEIGHT); 452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setHourGap(HOUR_GAP); 453ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mContext = context; 454ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mDeleteEventHelper = new DeleteEventHelper(context, null, false /* don't exit when done */); 455666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 456ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mController = controller; 457ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher = viewSwitcher; 458ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector = new GestureDetector(context, new CalendarGestureListener()); 459d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mScaleGestureDetector = new ScaleGestureDetector(getContext(), this); 46075d9b567e1fd3b9c6945cd0afe28781f5a19c6c8Michael Chan mNumDays = numDays; 461d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight == 0) { 462d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = Utils.getSharedPreference(mContext, 463d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan GeneralPreferences.KEY_DEFAULT_CELL_HEIGHT, DEFAULT_CELL_HEIGHT); 464d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 466ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan init(context); 467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void init(Context context) { 470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setFocusable(true); 471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allow focus in touch mode so that we can do keyboard shortcuts 473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // even after we've entered touch mode. 474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setFocusableInTouchMode(true); 475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setClickable(true); 476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setOnCreateContextMenuListener(this); 477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 478487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstDayOfWeek = Utils.getFirstDayOfWeek(context); 479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 480731f1cb808b7586b93615b408ab2636081fab0dcErik mCurrentTime = new Time(Utils.getTimeZone(context, mTZUpdater)); 481bd0e834aea317236d574f8738fe11a51fdc87968Erik long currentTime = System.currentTimeMillis(); 482bd0e834aea317236d574f8738fe11a51fdc87968Erik mCurrentTime.set(currentTime); 483bd0e834aea317236d574f8738fe11a51fdc87968Erik //The % makes it go off at the next increment of 5 minutes. 484bd0e834aea317236d574f8738fe11a51fdc87968Erik postDelayed(mUpdateCurrentTime, 485bd0e834aea317236d574f8738fe11a51fdc87968Erik UPDATE_CURRENT_TIME_DELAY - (currentTime % UPDATE_CURRENT_TIME_DELAY)); 486bd0e834aea317236d574f8738fe11a51fdc87968Erik mTodayJulianDay = Time.getJulianDay(currentTime, mCurrentTime.gmtoff); 487bd0e834aea317236d574f8738fe11a51fdc87968Erik 48864b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok mWeek_saturdayColor = mResources.getColor(R.color.week_saturday); 48964b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok mWeek_sundayColor = mResources.getColor(R.color.week_sunday); 490d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarDateBannerTextColor = mResources.getColor(R.color.calendar_date_banner_text_color); 4913eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarAllDayBackground = mResources.getColor(R.color.calendar_all_day_background); 492d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarAmPmLabel = mResources.getColor(R.color.calendar_ampm_label); 4933eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarDateBannerBackground = mResources.getColor(R.color.calendar_date_banner_background); 49411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// mCalendarDateSelected = mResources.getColor(R.color.calendar_date_selected); 4953eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarGridAreaBackground = mResources.getColor(R.color.calendar_grid_area_background); 496ba902466b19b11d587468e354edc58e542707747Michael Chan mCalendarGridAreaSelected = mResources.getColor(R.color.calendar_grid_area_selected); 497d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarGridLineHorizontalColor = mResources.getColor(R.color.calendar_grid_line_horizontal_color); 498d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarGridLineVerticalColor = mResources.getColor(R.color.calendar_grid_line_vertical_color); 4993eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCalendarGridLineInnerHorizontalColor = mResources.getColor(R.color.calendar_grid_line_inner_horizontal_color); 5003eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCalendarGridLineInnerVerticalColor = mResources.getColor(R.color.calendar_grid_line_inner_vertical_color); 5013eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// mCalendarHourBackground = mResources.getColor(R.color.calendar_hour_background); 502d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarHourLabel = mResources.getColor(R.color.calendar_hour_label); 50311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan// mCalendarHourSelected = mResources.getColor(R.color.calendar_hour_selected); 504146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionColor = mResources.getColor(R.color.selection); 505146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPressedColor = mResources.getColor(R.color.pressed); 506146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEventTextColor = mResources.getColor(R.color.calendar_event_selected_text_color); 507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextColor = mResources.getColor(R.color.calendar_event_text_color); 50811638ad4fb56b978770aebe75deac7a0e6ac60d2Erik 509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setColor(mEventTextColor); 510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setTextSize(EVENT_TEXT_FONT_SIZE); 511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setTextAlign(Paint.Align.LEFT); 512146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setAntiAlias(true); 513146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 514146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int gridLineColor = mResources.getColor(R.color.calendar_grid_line_highlight_color); 515146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mSelectionPaint; 516146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setColor(gridLineColor); 5173937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setStyle(Style.FILL); 518146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 519146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 520146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p = mPaint; 521146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 522146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 523146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allocate space for 2 weeks worth of weekday names so that we can 524146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // easily start the week display at any week day. 525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs = new String[14]; 526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also create an array of 2-letter abbreviations. 528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter = new String[14]; 529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) { 531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int index = i - Calendar.SUNDAY; 532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // e.g. Tue for Tuesday 533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_MEDIUM); 534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs[index + 7] = mDayStrs[index]; 535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // e.g. Tu for Tuesday 536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_SHORT); 53752b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer 53852b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer // If we don't have 2-letter day strings, fall back to 1-letter. 53952b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer if (mDayStrs2Letter[index].equals(mDayStrs[index])) { 54052b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer mDayStrs2Letter[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_SHORTEST); 54152b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer } 54252b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer 543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter[index + 7] = mDayStrs2Letter[index]; 544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 546146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out how much space we need for the 3-letter abbrev names 547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // in the worst case. 5483eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] dateStrs = {" 28", " 30"}; 551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDateStrWidth = computeMaxStringWidth(0, dateStrs, p); 5523eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDateStrWidth += computeMaxStringWidth(0, mDayStrs, p); 554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(HOURS_FONT_SIZE); 556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(null); 55769ab334d6988eda70ba53618506d23ebf7d7b405Erik updateIs24HourFormat(); 558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAmString = DateUtils.getAMPMString(Calendar.AM); 560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPmString = DateUtils.getAMPMString(Calendar.PM); 561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] ampm = {mAmString, mPmString}; 562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(AMPM_FONT_SIZE); 563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHoursWidth = computeMaxStringWidth(mHoursWidth, ampm, p); 564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHoursWidth += HOURS_MARGIN; 565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project LayoutInflater inflater; 567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView = inflater.inflate(R.layout.bubble_event, null); 569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView.setLayoutParams(new ViewGroup.LayoutParams( 570df279e3f9d5b0f189f812c52aca78d18178e4445Romain Guy ViewGroup.LayoutParams.MATCH_PARENT, 571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ViewGroup.LayoutParams.WRAP_CONTENT)); 572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup = new PopupWindow(context); 573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setContentView(mPopupView); 574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Resources.Theme dialogTheme = getResources().newTheme(); 575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dialogTheme.applyStyle(android.R.style.Theme_Dialog, true); 576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TypedArray ta = dialogTheme.obtainStyledAttributes(new int[] { 577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project android.R.attr.windowBackground }); 578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setBackgroundDrawable(ta.getDrawable(0)); 579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ta.recycle(); 580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Enable touching the popup window 582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView.setOnClickListener(this); 583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 584731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate = new Time(Utils.getTimeZone(context, mTZUpdater)); 585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = System.currentTimeMillis(); 586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.set(millis); 587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour = new int[mNumDays]; 589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent = new boolean[mNumDays]; 59002041687c35441e8a21cb763f1fc3a26525292efDavid Brown 59102041687c35441e8a21cb763f1fc3a26525292efDavid Brown // mLines is the array of points used with Canvas.drawLines() in 59202041687c35441e8a21cb763f1fc3a26525292efDavid Brown // drawGridBackground() and drawAllDayEvents(). Its size depends 59302041687c35441e8a21cb763f1fc3a26525292efDavid Brown // on the max number of lines that can ever be drawn by any single 59402041687c35441e8a21cb763f1fc3a26525292efDavid Brown // drawLines() call in either of those methods. 59502041687c35441e8a21cb763f1fc3a26525292efDavid Brown final int maxGridLines = (24 + 1) // max horizontal lines we might draw 59602041687c35441e8a21cb763f1fc3a26525292efDavid Brown + (mNumDays + 1); // max vertical lines we might draw 59702041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines = new float[maxGridLines * 4]; 598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * This is called when the popup window is pressed. 602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void onClick(View v) { 604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (v == mPopupView) { 605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pretend it was a trackball click because that will always 606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // jump to the "View event" screen. 607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball */); 608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 61169ab334d6988eda70ba53618506d23ebf7d7b405Erik public void updateIs24HourFormat() { 612ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mIs24HourFormat = DateFormat.is24HourFormat(mContext); 61369ab334d6988eda70ba53618506d23ebf7d7b405Erik mHourStrs = mIs24HourFormat ? CalendarData.s24Hours : CalendarData.s12HoursNoAmPm; 61469ab334d6988eda70ba53618506d23ebf7d7b405Erik } 61569ab334d6988eda70ba53618506d23ebf7d7b405Erik 616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Returns the start of the selected time in milliseconds since the epoch. 618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return selected time in UTC milliseconds since the epoch. 620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long getSelectedTimeInMillis() { 622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time.normalize(true /* ignore isDst */); 630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time getSelectedTime() { 633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 640146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.normalize(true /* ignore isDst */); 641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time; 642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 643146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 644146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 645146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Returns the start of the selected time in minutes since midnight, 646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * local time. The derived class must ensure that this is consistent 647146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * with the return value from getSelectedTimeInMillis(). 648146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 649146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int getSelectedMinutesSinceMidnight() { 650146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return mSelectionHour * MINUTES_PER_HOUR; 651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 652146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void setSelectedDay(Time time) { 654146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.set(time); 655146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mBaseDate.hour; 656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 658146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = mBaseDate.toMillis(false /* use isDst */); 659146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = Time.getJulianDay(millis, mBaseDate.gmtoff); 660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 661146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 662146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 665ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan // Don't draw the selection box if we are going to the "current" time 666ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan long currMillis = System.currentTimeMillis(); 667ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan boolean recent = (currMillis - 10000) < millis && millis < currMillis; 668ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan mSelectionMode = recent ? SELECTION_HIDDEN : SELECTION_SELECTED; 669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = true; 670146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 672146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public Time getSelectedDay() { 674146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 675146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 676146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 677146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 678146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 679146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.normalize(true /* ignore isDst */); 682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time; 683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 68583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan /** 686487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * return a negative number if "time" is comes before the visible time 687487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * range, a positive number if "time" is after the visible time range, and 0 688487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * if it is in the visible time range. 68983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan */ 690487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan public int compareToVisibleTimeRange(Time time) { 691487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 692487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedHour = mBaseDate.hour; 693487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedMinute = mBaseDate.minute; 694487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedSec = mBaseDate.second; 695487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 696487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.hour = 0; 697487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.minute = 0; 698487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.second = 0; 699487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 700030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) { 701030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown Log.d(TAG, "Begin " + mBaseDate.toString()); 702030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown Log.d(TAG, "Diff " + time.toString()); 703030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown } 704487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 70583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan // Compare beginning of range 70683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan int diff = Time.compare(time, mBaseDate); 707487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (diff > 0) { 708487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // Compare end of range 709487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.monthDay += mNumDays; 710487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.normalize(true); 711487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = Time.compare(time, mBaseDate); 712487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 713030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "End " + mBaseDate.toString()); 714487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 715487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.monthDay -= mNumDays; 716487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.normalize(true); 717487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (diff < 0) { 718487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // in visible time 719487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = 0; 720487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } else if (diff == 0) { 721487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // Midnight of following day 722487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = 1; 723487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 72483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 72583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 726030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "Diff: " + diff); 72783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 728487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.hour = savedHour; 729487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.minute = savedMinute; 730487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.second = savedSec; 731487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan return diff; 73283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 73383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 734146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void recalc() { 735146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Set the base date to the beginning of the week if we are displaying 736146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // 7 days at a time. 737146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 7) { 738146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int dayOfWeek = mBaseDate.weekDay; 739487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int diff = dayOfWeek - mFirstDayOfWeek; 740146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (diff != 0) { 741146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (diff < 0) { 742146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project diff += 7; 743146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 744146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.monthDay -= diff; 745146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.normalize(true /* ignore isDst */); 746146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 747146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 748146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 749146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final long start = mBaseDate.toMillis(false /* use isDst */); 750146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstJulianDay = Time.getJulianDay(start, mBaseDate.gmtoff); 751146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastJulianDay = mFirstJulianDay + mNumDays - 1; 752146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 753146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mMonthLength = mBaseDate.getActualMaximum(Time.MONTH_DAY); 754487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstVisibleDate = mBaseDate.monthDay; 755487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstVisibleDayOfWeek = mBaseDate.weekDay; 756146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 757146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 758146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 759146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected void onSizeChanged(int width, int height, int oldw, int oldh) { 760146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewWidth = width; 761146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewHeight = height; 762146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int gridAreaWidth = width - mHoursWidth; 763146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mCellWidth = (gridAreaWidth - (mNumDays * DAY_GAP)) / mNumDays; 764146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 765d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan // This would be about 1 day worth in a 7 day view 766d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan mHorizontalSnapBackThreshold = width / 7; 767d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan 768146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = new Paint(); 769146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(HOURS_FONT_SIZE); 770146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHoursTextHeight = (int) Math.abs(p.ascent()); 771146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project remeasure(width, height); 772146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 773146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 77446b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa /** 77546b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa * Measures the space needed for various parts of the view after 77646b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa * loading new events. This can change if there are all-day events. 77746b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa */ 778146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void remeasure(int width, int height) { 779146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 780146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear the array of earliest start times, and the array 781146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // indicating presence of an all-day event. 782146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++) { 783146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[day] = 25; // some big number 784146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent[day] = false; 785146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 786146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 787d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // Compute the layout relation between each event before measuring cell 788d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // width, as the cell width should be adjusted along with the relation. 78946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // 79046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // Examples: A (1:00pm - 1:01pm), B (1:02pm - 2:00pm) 79146b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // We should mark them as "overwapped". Though they are not overwapped logically, but 79246b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // minimum cell height implicitly expands the cell height of A and it should look like 79346b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa // (1:00pm - 1:15pm) after the cell height adjustment. 79446b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa 795146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the space needed for the all-day events, if any. 796146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Make a pass over all the events, and keep track of the maximum 797146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // number of all-day events in any one day. Also, keep track of 798146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the earliest event in each day. 799146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxAllDayEvents = 0; 80046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final ArrayList<Event> events = mEvents; 80146b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final int len = events.size(); 802c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa // Num of all-day-events on each day. 803c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int eventsCount[] = new int[mLastJulianDay - mFirstJulianDay + 1]; 804c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa Arrays.fill(eventsCount, 0); 805146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 806146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(ii); 807c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (event.startDay > mLastJulianDay || event.endDay < mFirstJulianDay) { 808146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 809c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 810146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.allDay) { 811c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int firstDay = Math.max(event.startDay, mFirstJulianDay); 812c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int lastDay = Math.min(event.endDay, mLastJulianDay); 813c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa for (int day = firstDay; day <= lastDay; day++) { 814c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa final int count = ++eventsCount[day - mFirstJulianDay]; 815c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (maxAllDayEvents < count) { 816c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa maxAllDayEvents = count; 817c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 818146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 819c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa 820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = event.startDay - mFirstJulianDay; 821146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int durationDays = event.endDay - event.startDay + 1; 822146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum < 0) { 823146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project durationDays += daynum; 824146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project daynum = 0; 825146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 826146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum + durationDays > mNumDays) { 827146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project durationDays = mNumDays - daynum; 828146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 829146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = daynum; durationDays > 0; day++, durationDays--) { 830146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent[day] = true; 831146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 832146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 833146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = event.startDay - mFirstJulianDay; 834146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int hour = event.startTime / 60; 835146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum >= 0 && hour < mEarliestStartHour[daynum]) { 836146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[daynum] = hour; 837146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also check the end hour in case the event spans more than 840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // one day. 841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project daynum = event.endDay - mFirstJulianDay; 842146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project hour = event.endTime / 60; 843146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (daynum < mNumDays && hour < mEarliestStartHour[daynum]) { 844146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[daynum] = hour; 845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 847146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 848146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mMaxAllDayEvents = maxAllDayEvents; 849146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 8509c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan // Calculate mAllDayHeight 8513eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mFirstCell = DAY_HEADER_HEIGHT; 852146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int allDayHeight = 0; 853146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxAllDayEvents > 0) { 854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is at most one all-day event per day, then use less 855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // space (but more than the space for a single event). 856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxAllDayEvents == 1) { 857146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project allDayHeight = SINGLE_ALLDAY_HEIGHT; 858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allow the all-day area to grow in height depending on the 860146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // number of all-day events we need to show, up to a limit. 861f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan allDayHeight = maxAllDayEvents * MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 862146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (allDayHeight > MAX_ALLDAY_HEIGHT) { 863146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project allDayHeight = MAX_ALLDAY_HEIGHT; 864146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 865146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 8663eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mFirstCell = DAY_HEADER_HEIGHT + allDayHeight + ALLDAY_TOP_MARGIN; 867146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 868146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = false; 869146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 870146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAllDayHeight = allDayHeight; 871146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 872146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mGridAreaHeight = height - mFirstCell; 873d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 874d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // The min is where 24 hours cover the entire visible area 875f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan mMinCellHeight = (height - DAY_HEADER_HEIGHT) / 24 - HOUR_GAP; 876d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight < mMinCellHeight) { 877d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = mMinCellHeight; 878d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 879d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 880697157470a6f0d8e7b806af9b4fb7fbe0bccae87Erik mNumHours = mGridAreaHeight / mCellHeight; 881146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setHourHeight(mCellHeight); 882146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 88327d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa final long minimumDurationMillis = (long) 88427d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa (MIN_EVENT_HEIGHT * DateUtils.MINUTE_IN_MILLIS / (mCellHeight / 60.0f)); 88546b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa Event.computePositions(events, minimumDurationMillis); 88646b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa 887c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Compute the top of our reachable view 888c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mMaxViewStartY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP) - mGridAreaHeight; 889d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 890d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.e(TAG, "mViewStartY: " + mViewStartY); 891d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.e(TAG, "mMaxViewStartY: " + mMaxViewStartY); 892d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 893d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mViewStartY > mMaxViewStartY) { 894d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = mMaxViewStartY; 895d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan computeFirstHour(); 896d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 897146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 898146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour == -1) { 899146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initFirstHour(); 900146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = 0; 901146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 902146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 903146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // When we change the base date, the number of all-day events may 904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // change and that changes the cell height. When we switch dates, 905146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // we use the mFirstHourOffset from the previous view, but that may 906146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // be too large for the new view if the cell height is smaller. 907146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHourOffset >= mCellHeight + HOUR_GAP) { 908146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = mCellHeight + HOUR_GAP - 1; 909146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 910146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mFirstHour * (mCellHeight + HOUR_GAP) - mFirstHourOffset; 911146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 91246b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final int eventAreaWidth = mNumDays * (mCellWidth + DAY_GAP); 913666fc5e8ddbac15c951aad738bd818ee307eae42Erik //When we get new events we don't want to dismiss the popup unless the event changes 914666fc5e8ddbac15c951aad738bd818ee307eae42Erik if (mSelectedEvent != null && mLastPopupEventID != mSelectedEvent.id) { 915666fc5e8ddbac15c951aad738bd818ee307eae42Erik mPopup.dismiss(); 916666fc5e8ddbac15c951aad738bd818ee307eae42Erik } 917146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setWidth(eventAreaWidth - 20); 918146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); 919146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 920146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 921146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 922146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Initialize the state for another view. The given view is one that has 923146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * its own bitmap and will use an animation to replace the current view. 924146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The current view and new view are either both Week views or both Day 925146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * views. They differ in their base date. 926146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 927146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param view the view to initialize. 928146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 929d190418220467c02327dd9b3ae1eae238889720bMichael Chan private void initView(DayView view) { 930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionHour = mSelectionHour; 931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectedEvents.clear(); 932146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mComputeSelectedEvents = true; 933146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mFirstHour = mFirstHour; 934146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mFirstHourOffset = mFirstHourOffset; 935146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.remeasure(getWidth(), getHeight()); 936e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 937146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectedEvent = null; 938146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mPrevSelectedEvent = null; 939487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan view.mFirstDayOfWeek = mFirstDayOfWeek; 940146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (view.mEvents.size() > 0) { 941146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionAllDay = mSelectionAllDay; 942146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 943146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionAllDay = false; 944146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 945146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 946146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Redraw the screen so that the selection box will be redrawn. We may 947146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // have scrolled to a different part of the day in some other view 948146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // so the selection box in this view may no longer be visible. 949146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.recalc(); 950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 951146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 952146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 953146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Switch to another view based on what was selected (an event or a free 954146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * slot) and how it was selected (by touch or by trackball). 955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 956146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param trackBallSelection true if the selection was made using the 957146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * trackball. 958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 959146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void switchViews(boolean trackBallSelection) { 960146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 963666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 964146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays > 1) { 965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the Week view. 966146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // With touch, we always switch to Day/Agenda View 967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // With track ball, if we selected a free slot, then create an event. 968146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected a specific event, switch to EventInfo view. 969146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (trackBallSelection) { 970146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 971146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EditEvent view 972146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 973146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 9749e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 9759e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan startMillis, endMillis, 0, 0); 976146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 977146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EventInfo view 9789e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 9799e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan selectedEvent.startMillis, selectedEvent.endMillis, 0, 0); 980146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 981146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 982146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This was a touch selection. If the touch selected a single 983146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // unambiguous event, then view that event. Otherwise go to 984146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Day/Agenda view. 985146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvents.size() == 1) { 9869e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 9879e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan selectedEvent.startMillis, selectedEvent.endMillis, 0, 0); 988146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 990146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 991146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the Day view. 992146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected a free slot, then create an event. 993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected an event, then go to the EventInfo view. 994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EditEvent view 996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 9989e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan 9999e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, startMillis, 10009e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan endMillis, 0, 0); 1001146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 10029e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 10039e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan selectedEvent.startMillis, selectedEvent.endMillis, 0, 0); 1004146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1005146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1006146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1007146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1008146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1009146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 1010146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 1011146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long duration = event.getEventTime() - event.getDownTime(); 1012146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1013146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (keyCode) { 1014146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 1015146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_HIDDEN) { 1016146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Don't do anything unless the selection is visible. 1017146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1018146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1019146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1020146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_PRESSED) { 1021146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This was the first press when there was nothing selected. 1022146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Change the selection from the "pressed" state to the 1023146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the "selected" state. We treat short-press and 1024146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // long-press the same here because nothing was selected. 1025146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1026146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1027146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1028146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1029146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1030146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check the duration to determine if this was a short press 1031146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (duration < ViewConfiguration.getLongPressTimeout()) { 1032146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball */); 1033146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1034146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 1035146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1036146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project performLongClick(); 1037146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1038146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1039ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// case KeyEvent.KEYCODE_BACK: 1040ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// if (event.isTracking() && !event.isCanceled()) { 1041ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mPopup.dismiss(); 1042ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.finish(); 1043ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// return true; 1044ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// } 1045ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// break; 1046146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1047146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyUp(keyCode, event); 1048146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1049146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1050146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1051146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 1052146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_HIDDEN) { 1053146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT 1054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_UP 1055146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { 1056146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Display the selection box but don't move or select it 1057146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on this key press. 1058146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1059146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1060146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1061146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 1062146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Display the selection box but don't select it 1063146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on this key press. 1064146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_PRESSED; 1065146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1066146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1067146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1068146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1069146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1070146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1071146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 1072146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean redraw; 1073146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectionDay = mSelectionDay; 1074146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1075146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (keyCode) { 1076146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DEL: 1077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Delete the selected event, if any 1078146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 1079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 1080146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return false; 1081146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1082146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 1083666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1084146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1085146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long begin = selectedEvent.startMillis; 1086146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long end = selectedEvent.endMillis; 1087146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long id = selectedEvent.id; 1088146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDeleteEventHelper.delete(begin, end, id, -1); 1089146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1090146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_ENTER: 1091146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball or keyboard */); 1092146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1093146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_BACK: 1094b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan if (event.getRepeatCount() == 0) { 1095b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan event.startTracking(); 1096b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan return true; 1097b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan } 1098b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan return super.onKeyDown(keyCode, event); 1099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_LEFT: 1100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 1101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = mSelectedEvent.nextLeft; 1102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 1104666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionDay -= 1; 1106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project redraw = true; 1108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_RIGHT: 1111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 1112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = mSelectedEvent.nextRight; 1113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 1115666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionDay += 1; 1117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project redraw = true; 1119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_UP: 1122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 1123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = mSelectedEvent.nextUp; 1124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 1126666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!mSelectionAllDay) { 1128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour -= 1; 1129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project adjustHourSelection(); 1130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project redraw = true; 1135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_DOWN: 1138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 1139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = mSelectedEvent.nextDown; 1140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 1142666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay) { 1144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = false; 1145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour++; 1147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project adjustHourSelection(); 1148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project redraw = true; 1153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project default: 1156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyDown(keyCode, event); 1157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((selectionDay < mFirstJulianDay) || (selectionDay > mLastJulianDay)) { 1160d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getNextView(); 1161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time date = view.mBaseDate; 1162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.set(mBaseDate); 1163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectionDay < mFirstJulianDay) { 1164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay -= mNumDays; 1165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay += mNumDays; 1167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.normalize(true /* ignore isDst */); 1169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = selectionDay; 1170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initView(view); 117283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 117383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time end = new Time(date); 117483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan end.monthDay += mNumDays - 1; 117583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Log.d(TAG, "onKeyDown"); 11763458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan mController.sendEvent(this, EventType.GO_TO, date, end, -1, ViewType.CURRENT); 1177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = selectionDay; 1180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (redraw) { 1184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyDown(keyCode, event); 1189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1191ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private View switchViews(boolean forward, float xOffSet, float width) { 1192030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "switchViews(" + forward + ")..."); 1193ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float progress = Math.abs(xOffSet) / width; 1194ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (progress > 1.0f) { 1195ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan progress = 1.0f; 1196ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1197ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1198ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float inFromXValue, inToXValue; 1199ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float outFromXValue, outToXValue; 1200ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (forward) { 1201ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inFromXValue = 1.0f - progress; 1202ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inToXValue = 0.0f; 1203ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outFromXValue = -progress; 1204ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outToXValue = -1.0f; 1205ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } else { 1206ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inFromXValue = progress - 1.0f; 1207ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inToXValue = 0.0f; 1208ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outFromXValue = progress; 1209ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outToXValue = 1.0f; 1210ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1211ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1212ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // We have to allocate these animation objects each time we switch views 1213ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // because that is the only way to set the animation parameters. 1214ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan TranslateAnimation inAnimation = new TranslateAnimation( 1215ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, inFromXValue, 1216ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, inToXValue, 1217ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f, 1218ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f); 1219ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1220ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan TranslateAnimation outAnimation = new TranslateAnimation( 1221ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, outFromXValue, 1222ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, outToXValue, 1223ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f, 1224ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f); 1225ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1226ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // Reduce the animation duration based on how far we have already swiped. 1227ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan long duration = (long) (ANIMATION_DURATION * (1.0f - progress)); 1228ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inAnimation.setDuration(duration); 1229ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outAnimation.setDuration(duration); 1230ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.setInAnimation(inAnimation); 1231ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.setOutAnimation(outAnimation); 1232ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1233d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getCurrentView(); 1234ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.cleanup(); 1235ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.showNext(); 1236d190418220467c02327dd9b3ae1eae238889720bMichael Chan view = (DayView) mViewSwitcher.getCurrentView(); 1237ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.requestFocus(); 1238ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.reloadEvents(); 1239e98dd73c67205b01f5348271d9a7a630003ecf52David Brown 1240e98dd73c67205b01f5348271d9a7a630003ecf52David Brown // Update the mini-month (but defer it until the animation 1241e98dd73c67205b01f5348271d9a7a630003ecf52David Brown // completes, to avoid stutter.) 1242e98dd73c67205b01f5348271d9a7a630003ecf52David Brown final Time start = new Time(view.mBaseDate); 1243e98dd73c67205b01f5348271d9a7a630003ecf52David Brown final Time end = new Time(view.mBaseDate); 1244e98dd73c67205b01f5348271d9a7a630003ecf52David Brown end.monthDay += mNumDays; 1245e98dd73c67205b01f5348271d9a7a630003ecf52David Brown end.normalize(true); 1246e98dd73c67205b01f5348271d9a7a630003ecf52David Brown postDelayed(new Runnable() { 1247e98dd73c67205b01f5348271d9a7a630003ecf52David Brown public void run() { 1248e98dd73c67205b01f5348271d9a7a630003ecf52David Brown mController.sendEvent(this, EventType.GO_TO, 1249e98dd73c67205b01f5348271d9a7a630003ecf52David Brown start, end, -1, ViewType.CURRENT); 1250e98dd73c67205b01f5348271d9a7a630003ecf52David Brown } 1251e98dd73c67205b01f5348271d9a7a630003ecf52David Brown }, duration); 1252e98dd73c67205b01f5348271d9a7a630003ecf52David Brown 1253ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return view; 1254ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1255ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is called after scrolling stops to move the selected hour 1257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // to the visible part of the screen. 1258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void resetSelectedHour() { 1259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < mFirstHour + 1) { 1260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + 1; 1261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionHour > mFirstHour + mNumHours - 3) { 1265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + mNumHours - 3; 1266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void initFirstHour() { 1273d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mFirstHour = mSelectionHour - mNumHours / 5; 1274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 0) { 1275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = 0; 1276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mFirstHour + mNumHours > 24) { 1277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = 24 - mNumHours; 1278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Recomputes the first full hour that is visible on screen after the 1283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * screen is scrolled. 1284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeFirstHour() { 1286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the first full hour that is visible on screen 1287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = (mViewStartY + mCellHeight + HOUR_GAP - 1) / (mCellHeight + HOUR_GAP); 1288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = mFirstHour * (mCellHeight + HOUR_GAP) - mViewStartY; 1289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void adjustHourSelection() { 1292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < 0) { 1293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = 0; 1294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mMaxAllDayEvents > 0) { 1295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = true; 1297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour > 23) { 1301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = 23; 1302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the selected hour is at least 2 time slots from the top and 1305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // bottom of the screen, then don't scroll the view. 1306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < mFirstHour + 1) { 1307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there are all-days events for the selected day but there 1308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // are no more normal events earlier in the day, then jump to 1309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the all-day event area. 1310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Exception 1: allow the user to scroll to 8am with the trackball 1311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // before jumping to the all-day event area. 1312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Exception 2: if 12am is on screen, then allow the user to select 1313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // 12am before going up to the all-day event area. 1314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 1315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mMaxAllDayEvents > 0 && mEarliestStartHour[daynum] > mSelectionHour 1316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && mFirstHour > 0 && mFirstHour < 8) { 1317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = true; 1319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + 1; 1320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour > 0) { 1324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour -= 1; 1325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY -= (mCellHeight + HOUR_GAP); 1326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 1327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 1328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour > mFirstHour + mNumHours - 3) { 1334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 24 - mNumHours) { 1335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour += 1; 1336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY += (mCellHeight + HOUR_GAP); 1337c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik if (mViewStartY > mMaxViewStartY) { 1338c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mViewStartY = mMaxViewStartY; 1339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mFirstHour == 24 - mNumHours && mFirstHourOffset > 0) { 1342c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mViewStartY = mMaxViewStartY; 1343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project void clearCachedEvents() { 1348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastReloadMillis = 0; 1349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Runnable mCancelCallback = new Runnable() { 1352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 1353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project clearCachedEvents(); 1354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 1356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 135746b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa /* package */ void reloadEvents() { 1358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against this being called before this view has been 1359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // initialized. 1360ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// if (mContext == null) { 1361ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// return; 1362ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// } 1363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1364731f1cb808b7586b93615b408ab2636081fab0dcErik // Make sure our time zones are up to date 1365731f1cb808b7586b93615b408ab2636081fab0dcErik mTZUpdater.run(); 1366731f1cb808b7586b93615b408ab2636081fab0dcErik 1367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The start date is the beginning of the week at 12am 1372731f1cb808b7586b93615b408ab2636081fab0dcErik Time weekStart = new Time(Utils.getTimeZone(mContext, mTZUpdater)); 1373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.set(mBaseDate); 1374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.hour = 0; 1375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.minute = 0; 1376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.second = 0; 1377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = weekStart.normalize(true /* ignore isDst */); 1378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Avoid reloading events unnecessarily. 1380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (millis == mLastReloadMillis) { 1381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastReloadMillis = millis; 1384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // load events in the background 1386ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.startProgressSpinner(); 1387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final ArrayList<Event> events = new ArrayList<Event>(); 1388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventLoader.loadEventsInBackground(mNumDays, events, millis, new Runnable() { 1389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 1390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEvents = events; 139108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mAllDayEvents == null) { 139208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents = new ArrayList<Event>(); 139308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 139408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents.clear(); 139508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 139608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 139708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Create a shorter array for all day events 139808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan for(Event e : events) { 139908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (e.allDay) { 140008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents.add(e); 140108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 140208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 140308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 140408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // New events, new layouts 140508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mLayouts == null || mLayouts.length < events.size()) { 140608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mLayouts = new StaticLayout[events.size()]; 140708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 140808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Arrays.fill(mLayouts, null); 14093e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 141008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 141108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mAllDayLayouts == null || mAllDayLayouts.length < mAllDayEvents.size()) { 141208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayLayouts = new StaticLayout[events.size()]; 141308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 141408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Arrays.fill(mAllDayLayouts, null); 141508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 141608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 1417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = true; 1418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 1420ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.stopProgressSpinner(); 1421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }, mCancelCallback); 1424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected void onDraw(Canvas canvas) { 1428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mRemeasure) { 1429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project remeasure(getWidth(), getHeight()); 1430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = false; 1431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1432c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.save(); 1433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1434c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik float yTranslate = -mViewStartY + DAY_HEADER_HEIGHT + mAllDayHeight; 1435c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // offset canvas by the current drag and header position 1436c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(-mViewStartX, yTranslate); 1437c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // clip to everything below the allDay area 1438c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik Rect dest = mDestRect; 1439c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.top = (int) (mFirstCell - yTranslate); 1440c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.bottom = (int) (mViewHeight - yTranslate); 1441c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.left = 0; 1442c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.right = mViewWidth; 1443c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.save(); 1444c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.clipRect(dest); 1445c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Draw the movable part of the view 1446c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik doDraw(canvas); 1447c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // restore to having no clip 1448c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.restore(); 1449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 1451c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik float xTranslate; 1452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartX > 0) { 1453c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik xTranslate = mViewWidth; 1454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1455c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik xTranslate = -mViewWidth; 1456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1457c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Move the canvas around to prep it for the next view 1458c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // specifically, shift it by a screen and undo the 1459c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // yTranslation which will be redone in the nextView's onDraw(). 1460c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(xTranslate, -yTranslate); 1461d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView nextView = (DayView) mViewSwitcher.getNextView(); 1462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Prevent infinite recursive calls to onDraw(). 1464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project nextView.mTouchMode = TOUCH_MODE_INITIAL_STATE; 1465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project nextView.onDraw(canvas); 1467c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Move it back for this view 1468c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(-xTranslate, 0); 1469c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik } else { 1470c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // If we drew another view we already translated it back 1471c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // If we didn't draw another view we should be at the edge of the 1472c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // screen 1473c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(mViewStartX, -yTranslate); 1474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the fixed areas (that don't scroll) directly to the canvas. 1477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAfterScroll(canvas); 1478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = false; 1479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.restore(); 1480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAfterScroll(Canvas canvas) { 1483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mPaint; 1484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r = mRect; 1485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mMaxAllDayEvents != 0) { 14871ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan drawAllDayEvents(mFirstJulianDay, mNumDays, canvas, p); 14883eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// drawUpperLeftCorner(r, canvas, p); 1489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1491c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik drawScrollLine(r, canvas, p); 1492c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik 14933eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan drawDayHeaderLoop(r, canvas, p); 1494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the AM and PM indicators if we're in 12 hour mode 1496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!mIs24HourFormat) { 1497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAmPm(canvas, p); 1498146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Update the popup window showing the event details, but only if 1501146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // we are not scrolling and we have focus. 1502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!mScrolling && isFocused()) { 1503146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project updateEventDetails(); 1504146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1505146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1506146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This isn't really the upper-left corner. It's the square area just 1508146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // below the upper-left corner, above the hours and to the left of the 1509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // all-day area. 15103eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// private void drawUpperLeftCorner(Rect r, Canvas canvas, Paint p) { 15113eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// p.setColor(mCalendarHourBackground); 15123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// r.top = DAY_HEADER_HEIGHT; 15133eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// r.bottom = r.top + mAllDayHeight + ALLDAY_TOP_MARGIN; 15143eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// r.left = 0; 15153eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// r.right = mHoursWidth; 15163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// canvas.drawRect(r, p); 15173eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan// } 1518146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1519c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik private void drawScrollLine(Rect r, Canvas canvas, Paint p) { 15201ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setColor(mCalendarGridLineInnerHorizontalColor); 1521c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(false); 15221ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 15231ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int y = mFirstCell - 1; 15241ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawLine(0, y, mHoursWidth + (mCellWidth + DAY_GAP) * mNumDays, y, p); 1525c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(true); 1526c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik } 1527c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik 1528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawDayHeaderLoop(Rect r, Canvas canvas, Paint p) { 1529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the horizontal day background banner 15303eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarDateBannerBackground); 15313eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = 0; 15323eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = DAY_HEADER_HEIGHT; 15333eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = 0; 15343eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mHoursWidth + mNumDays * (mCellWidth + DAY_GAP); 15353eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 15363eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // 1537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the extra space on the right side with the default background 15383eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = r.right; 15393eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mViewWidth; 15403eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 15413eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 15433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int todayNum = mTodayJulianDay - mFirstJulianDay; 15443eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mNumDays > 1) { 15453eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.top = 0; 15463eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.bottom = DAY_HEADER_HEIGHT; 15473eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 15483eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Highlight today 15493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mFirstJulianDay <= mTodayJulianDay 15503eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan && mTodayJulianDay < (mFirstJulianDay + mNumDays)) { 15513eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.left = mHoursWidth + todayNum * (mCellWidth + DAY_GAP); 15523eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.right = r.left + mCellWidth; 15533eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable.setBounds(r); 15543eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable.draw(canvas); 15553eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 15563eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 15573eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw a highlight on the selected day (if any), but only if we are 15583eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // displaying more than one day. 155911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // 156011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // int selectedDayNum = mSelectionDay - mFirstJulianDay; 156111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // if (mSelectionMode != SELECTION_HIDDEN && selectedDayNum >= 0 156211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // && selectedDayNum < mNumDays) { 156311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // p.setColor(mCalendarDateSelected); 156411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // r.left = mHoursWidth + selectedDayNum * (mCellWidth + DAY_GAP); 156511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // r.right = r.left + mCellWidth; 156611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // canvas.drawRect(r, p); 156711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // } 1568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 15703eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTypeface(mBold); 15713eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextAlign(Paint.Align.RIGHT); 15723eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float x = mHoursWidth; 1573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaX = mCellWidth + DAY_GAP; 1574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cell = mFirstJulianDay; 1575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] dayNames; 1577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mDateStrWidth < mCellWidth) { 1578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dayNames = mDayStrs; 1579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dayNames = mDayStrs2Letter; 1581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1583d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setAntiAlias(true); 1584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++, cell++) { 15851f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan int dayOfWeek = day + mFirstVisibleDayOfWeek; 15861f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan if (dayOfWeek >= 14) { 15871f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan dayOfWeek -= 14; 1588487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 1589487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 15903eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int color = mCalendarDateBannerTextColor; 1591071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (mNumDays == 1) { 1592071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (dayOfWeek == Time.SATURDAY) { 1593071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_saturdayColor; 1594071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else if (dayOfWeek == Time.SUNDAY) { 1595071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_sundayColor; 1596071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } 1597071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else { 1598071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa final int column = day % 7; 1599071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (Utils.isSaturday(column, mFirstDayOfWeek)) { 1600071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_saturdayColor; 1601071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else if (Utils.isSunday(column, mFirstDayOfWeek)) { 1602071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_sundayColor; 1603071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } 16043eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 16053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 16063eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan color &= 0x00FFFFFF; 16073eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (todayNum == day) { 16083eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan color |= DAY_HEADER_TODAY_ALPHA; 1609487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } else { 16103eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan color |= DAY_HEADER_ALPHA; 1611487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 1612487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 16133eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(color); 1614487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan drawDayHeader(dayNames[dayOfWeek], day, cell, x, canvas, p); 1615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project x += deltaX; 1616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 16173eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTypeface(null); 1618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAmPm(Canvas canvas, Paint p) { 1621d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarAmPmLabel); 1622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(AMPM_FONT_SIZE); 1623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 1624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 1625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPaint.setTextAlign(Paint.Align.RIGHT); 1626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String text = mAmString; 1627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour >= 12) { 1628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = mPmString; 1629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = mFirstCell + mFirstHourOffset + 2 * mHoursTextHeight + HOUR_GAP; 1631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int right = mHoursWidth - HOURS_RIGHT_MARGIN; 1632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.drawText(text, right, y, p); 1633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 12 && mFirstHour + mNumHours > 12) { 1635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also draw the "PM" 1636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = mPmString; 1637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y = mFirstCell + mFirstHourOffset + (12 - mFirstHour) * (mCellHeight + HOUR_GAP) 1638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project + 2 * mHoursTextHeight + HOUR_GAP; 1639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.drawText(text, right, y, p); 1640146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1643f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan private void drawCurrentTimeLine(Rect r, final int left, final int top, Canvas canvas, 1644f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan Paint p) { 16453eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.left = left - CURRENT_TIME_LINE_SIDE_BUFFER; 16461ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = left + mCellWidth + DAY_GAP + CURRENT_TIME_LINE_SIDE_BUFFER; 16473eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 16483eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.top = top - mCurrentTimeLine.getIntrinsicHeight() / 2; 16493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.bottom = r.top + mCurrentTimeLine.getIntrinsicHeight(); 1650bd0e834aea317236d574f8738fe11a51fdc87968Erik 16513eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine.setBounds(r); 16523eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine.draw(canvas); 1653bd0e834aea317236d574f8738fe11a51fdc87968Erik } 1654bd0e834aea317236d574f8738fe11a51fdc87968Erik 1655146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void doDraw(Canvas canvas) { 1656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mPaint; 1657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r = mRect; 1658146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1659146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawGridBackground(r, canvas, p); 1660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawHours(r, canvas, p); 1661146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1662146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw each day 1663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int x = mHoursWidth; 1664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaX = mCellWidth + DAY_GAP; 1665146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cell = mFirstJulianDay; 1666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++, cell++) { 166708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // TODO Wow, this needs cleanup. drawEvents loop through all the 166808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // events on every call. 1669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawEvents(cell, x, HOUR_GAP, canvas, p); 1670bd0e834aea317236d574f8738fe11a51fdc87968Erik //If this is today 1671bd0e834aea317236d574f8738fe11a51fdc87968Erik if(cell == mTodayJulianDay) { 16721ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int lineY = mCurrentTime.hour * (mCellHeight + HOUR_GAP) 16731ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan + ((mCurrentTime.minute * mCellHeight) / 60) + 1; 16741ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 1675bd0e834aea317236d574f8738fe11a51fdc87968Erik //And the current time shows up somewhere on the screen 1676bd0e834aea317236d574f8738fe11a51fdc87968Erik if(lineY >= mViewStartY && lineY < mViewStartY + mViewHeight - 2) { 1677bd0e834aea317236d574f8738fe11a51fdc87968Erik drawCurrentTimeLine(r, x, lineY, canvas, p); 1678bd0e834aea317236d574f8738fe11a51fdc87968Erik } 1679bd0e834aea317236d574f8738fe11a51fdc87968Erik } 1680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project x += deltaX; 1681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawHours(Rect r, Canvas canvas, Paint p) { 16853eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Comment out as the background will be a drawable 16863eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 1687146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the background for the hour labels 16883eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarHourBackground); 16893eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = 0; 16903eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = 24 * (mCellHeight + HOUR_GAP) + HOUR_GAP; 16913eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = 0; 16923eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mHoursWidth; 16933eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1694146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1695146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the bottom left corner with the default grid background 16963eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = r.bottom; 16973eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = mBitmapHeight; 16983eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 16993eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1700146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1701146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw a highlight on the selected hour (if needed) 1702ba902466b19b11d587468e354edc58e542707747Michael Chan if (mSelectionMode != SELECTION_HIDDEN && !mSelectionAllDay) { 1703ba902466b19b11d587468e354edc58e542707747Michael Chan // p.setColor(mCalendarHourSelected); 17043937a47bc5a1afb9701e1d0565fae31f5800590dErik int daynum = mSelectionDay - mFirstJulianDay; 1705ba902466b19b11d587468e354edc58e542707747Michael Chan r.top = mSelectionHour * (mCellHeight + HOUR_GAP); 17061ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top + mCellHeight + HOUR_GAP; 17071ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = mHoursWidth + daynum * (mCellWidth + DAY_GAP); 17083937a47bc5a1afb9701e1d0565fae31f5800590dErik r.right = r.left + mCellWidth + DAY_GAP; 1709ba902466b19b11d587468e354edc58e542707747Michael Chan 1710ba902466b19b11d587468e354edc58e542707747Michael Chan // Draw a border around the highlighted grid hour. 17111ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // drawEmptyRect(canvas, r, mSelectionPaint.getColor()); 1712ba902466b19b11d587468e354edc58e542707747Michael Chan saveSelectionPosition(r.left, r.top, r.right, r.bottom); 17133937a47bc5a1afb9701e1d0565fae31f5800590dErik 17143937a47bc5a1afb9701e1d0565fae31f5800590dErik // Also draw the highlight on the grid 17153937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setColor(mCalendarGridAreaSelected); 17163937a47bc5a1afb9701e1d0565fae31f5800590dErik r.top += HOUR_GAP; 17173937a47bc5a1afb9701e1d0565fae31f5800590dErik r.right -= DAY_GAP; 17183937a47bc5a1afb9701e1d0565fae31f5800590dErik canvas.drawRect(r, p); 1719ba902466b19b11d587468e354edc58e542707747Michael Chan } 1720146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1721d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarHourLabel); 1722146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(HOURS_FONT_SIZE); 1723146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 1724146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextAlign(Paint.Align.RIGHT); 1725146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 1726146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1727146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int right = mHoursWidth - HOURS_RIGHT_MARGIN; 1728146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = HOUR_GAP + mHoursTextHeight; 1729146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1730146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < 24; i++) { 1731146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String time = mHourStrs[i]; 1732146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.drawText(time, right, y, p); 1733146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += mCellHeight + HOUR_GAP; 1734146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1735146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1736146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17373eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private void drawDayHeader(String dayStr, int day, int cell, float x, Canvas canvas, Paint p) { 1738487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int dateNum = mFirstVisibleDate + day; 1739146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (dateNum > mMonthLength) { 1740146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dateNum -= mMonthLength; 1741146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1742146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 17443eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan String dateNumStr = String.valueOf(dateNum); 17453eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mNumDays > 1) { 17463eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float y = DAY_HEADER_HEIGHT - DAY_HEADER_BOTTOM_MARGIN; 17473eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 17483eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 17493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += mCellWidth - DAY_HEADER_RIGHT_MARGIN; 17503eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 17513eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dateNumStr, x, y, p); 17523eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 17533eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the week 17543eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x -= p.measureText(dateNumStr) + DAY_HEADER_LEFT_MARGIN; 17553eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 17563eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dayStr, x, y, p); 1757146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 17583eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float y = DAY_HEADER_HEIGHT - DAY_HEADER_ONE_DAY_BOTTOM_MARGIN; 175911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setTextAlign(Paint.Align.LEFT); 1760146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17613eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the week 17623eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += DAY_HEADER_ONE_DAY_LEFT_MARGIN; 17633eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 17643eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dayStr, x, y, p); 1765d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan 17663eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 17673eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += p.measureText(dayStr) + DAY_HEADER_ONE_DAY_RIGHT_MARGIN; 17683eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 17693eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dateNumStr, x, y, p); 1770d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan } 1771146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1772146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1773146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawGridBackground(Rect r, Canvas canvas, Paint p) { 1774146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint.Style savedStyle = p.getStyle(); 1775146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17763eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the outer horizontal grid lines 1777d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarGridLineHorizontalColor); 17789c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan p.setStyle(Style.FILL); 17793937a47bc5a1afb9701e1d0565fae31f5800590dErik 1780146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 17813eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startX = 0; 17823eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopX = mHoursWidth + (mCellWidth + DAY_GAP) * mNumDays; 1783000ba1109e2f4e527e9227fe341598ceeb3fbca6Michael Chan float y = 0; 17843eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaY = mCellHeight + HOUR_GAP; 17853937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setStrokeWidth(GRID_LINE_WIDTH); 178602041687c35441e8a21cb763f1fc3a26525292efDavid Brown int linesIndex = 0; 1787146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int hour = 0; hour <= 24; hour++) { 178802041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startX; 178902041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 179002041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopX; 179102041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 1792146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += deltaY; 1793146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 179402041687c35441e8a21cb763f1fc3a26525292efDavid Brown if (mCalendarGridLineVerticalColor != mCalendarGridLineHorizontalColor) { 179502041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 179602041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 179702041687c35441e8a21cb763f1fc3a26525292efDavid Brown p.setColor(mCalendarGridLineVerticalColor); 179802041687c35441e8a21cb763f1fc3a26525292efDavid Brown } 1799146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 18003eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the outer vertical grid lines 18013eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startY = 0; 18023eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP); 18033eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaX = mCellWidth + DAY_GAP; 18041ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan float x = mHoursWidth; 1805146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++) { 18061ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x += deltaX; 180702041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 180802041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 180902041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 181002041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 1811146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 181202041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 1813146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 18143eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner horizontal grid lines 18153eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerHorizontalColor); 18163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 18173eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan y = 0; 181802041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 18193eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int hour = 0; hour <= 24; hour++) { 182002041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startX; 182102041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 182202041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopX; 182302041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 18243eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan y += deltaY; 18253eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 182602041687c35441e8a21cb763f1fc3a26525292efDavid Brown if (mCalendarGridLineInnerVerticalColor != mCalendarGridLineInnerHorizontalColor) { 182702041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 182802041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 182902041687c35441e8a21cb763f1fc3a26525292efDavid Brown p.setColor(mCalendarGridLineInnerVerticalColor); 183002041687c35441e8a21cb763f1fc3a26525292efDavid Brown } 18313eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 18323eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner vertical grid lines 18331ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x = mHoursWidth; 18343eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int day = 0; day < mNumDays; day++) { 18351ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x += deltaX; 183602041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 183702041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 183802041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 183902041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 18403eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 184102041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 18423eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 1843146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Restore the saved style. 1844146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setStyle(savedStyle); 1845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 1846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1847146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1848146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event getSelectedEvent() { 1849146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 1850146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // There is no event at the selected hour, so create a new event. 1851146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return getNewEvent(mSelectionDay, getSelectedTimeInMillis(), 1852146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getSelectedMinutesSinceMidnight()); 1853146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return mSelectedEvent; 1855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1857146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean isEventSelected() { 1858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return (mSelectedEvent != null); 1859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1860146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1861146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event getNewEvent() { 1862146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return getNewEvent(mSelectionDay, getSelectedTimeInMillis(), 1863146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getSelectedMinutesSinceMidnight()); 1864146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1865146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1866146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project static Event getNewEvent(int julianDay, long utcMillis, 1867146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int minutesSinceMidnight) { 1868146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = Event.newInstance(); 1869146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startDay = julianDay; 1870146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endDay = julianDay; 1871146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startMillis = utcMillis; 1872146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endMillis = event.startMillis + MILLIS_PER_HOUR; 1873146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startTime = minutesSinceMidnight; 1874146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endTime = event.startTime + MINUTES_PER_HOUR; 1875146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return event; 1876146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1877146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1878146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int computeMaxStringWidth(int currentMax, String[] strings, Paint p) { 1879146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float maxWidthF = 0.0f; 1880146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1881146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = strings.length; 1882146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < len; i++) { 1883146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float width = p.measureText(strings[i]); 1884146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxWidthF = Math.max(width, maxWidthF); 1885146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1886146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxWidth = (int) (maxWidthF + 0.5); 1887146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxWidth < currentMax) { 1888146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxWidth = currentMax; 1889146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1890146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return maxWidth; 1891146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1892146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1893146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void saveSelectionPosition(float left, float top, float right, float bottom) { 1894146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.left = (int) left; 1895146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.right = (int) right; 1896146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.top = (int) top; 1897146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.bottom = (int) bottom; 1898146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1899146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1900146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect getCurrentSelectionPosition() { 1901146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect box = new Rect(); 1902146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.top = mSelectionHour * (mCellHeight + HOUR_GAP); 1903146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.bottom = box.top + mCellHeight + HOUR_GAP; 1904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 1905146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.left = mHoursWidth + daynum * (mCellWidth + DAY_GAP); 1906146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.right = box.left + mCellWidth + DAY_GAP; 1907146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return box; 1908146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1909146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 19101ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void setupTextRect(Rect r) { 19111ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom <= r.top || r.right <= r.left) { 19121ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top; 19131ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = r.left; 191436a4668f603c432d08ad156cd7c731f9838c0212Michael Chan return; 191536a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 191636a4668f603c432d08ad156cd7c731f9838c0212Michael Chan 19171ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom - r.top > EVENT_TEXT_TOP_MARGIN + EVENT_TEXT_BOTTOM_MARGIN) { 19181ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top += EVENT_TEXT_TOP_MARGIN; 19191ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom -= EVENT_TEXT_BOTTOM_MARGIN; 192036a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 19211ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.right - r.left > EVENT_TEXT_LEFT_MARGIN + EVENT_TEXT_RIGHT_MARGIN) { 19221ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left += EVENT_TEXT_LEFT_MARGIN; 19231ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right -= EVENT_TEXT_RIGHT_MARGIN; 192436a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 19259c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan } 19269c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan 19271ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void setupAllDayTextRect(Rect r) { 19281ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom <= r.top || r.right <= r.left) { 19291ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top; 19301ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = r.left; 193136a4668f603c432d08ad156cd7c731f9838c0212Michael Chan return; 193236a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 193336a4668f603c432d08ad156cd7c731f9838c0212Michael Chan 19341ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom - r.top > EVENT_ALL_DAY_TEXT_TOP_MARGIN + EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN) { 19351ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top += EVENT_ALL_DAY_TEXT_TOP_MARGIN; 19361ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom -= EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN; 193736a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 19381ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.right - r.left > EVENT_ALL_DAY_TEXT_LEFT_MARGIN + EVENT_ALL_DAY_TEXT_RIGHT_MARGIN) { 19391ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left += EVENT_ALL_DAY_TEXT_LEFT_MARGIN; 19401ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right -= EVENT_ALL_DAY_TEXT_RIGHT_MARGIN; 194136a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 19429c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan } 19439c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan 19443e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh /** 19453e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh * Return the layout for a numbered event. Create it if not already existing 19463e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh */ 194708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout getEventLayout(StaticLayout[] layouts, int i, Event event, Paint paint, 194808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Rect r) { 194908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (i < 0 || i >= layouts.length) { 19500a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan return null; 19510a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan } 19520a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan 195308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = layouts[i]; 1954f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan // Check if we have already initialized the StaticLayout and that 1955f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan // the width hasn't changed (due to vertical resizing which causes 1956f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan // re-layout of events at min height) 19571ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (layout == null || r.width() != layout.getWidth()) { 1958f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan String text = drawTextSanitizer(event.getTitleAndLocation(), MAX_EVENT_TEXT_LEN); 19593e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 19603e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh // Leave a one pixel boundary on the left and right of the rectangle for the event 19611ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan layout = new StaticLayout(text, 0, text.length(), new TextPaint(paint), r.width(), 19621ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true, null, r.width()); 19633e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 196408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan layouts[i] = layout; 19653e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 19663e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 19673e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh return layout; 19683e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 19693e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 19701ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void drawAllDayEvents(int firstDay, int numDays, Canvas canvas, Paint p) { 19711ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (mSelectionAllDay) { 19721ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // Draw the highlight on the selected all-day area 19731ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mRect.top = DAY_HEADER_HEIGHT + 1; 19741ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mRect.bottom = mRect.top + mAllDayHeight + ALLDAY_TOP_MARGIN - 2; 19751ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int daynum = mSelectionDay - mFirstJulianDay; 19761ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mRect.left = mHoursWidth + daynum * (mCellWidth + DAY_GAP); 19771ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mRect.right = mRect.left + mCellWidth + DAY_GAP - 1; 19781ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setColor(mCalendarGridAreaSelected); 19791ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawRect(mRect, p); 19803e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 19813e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 1982146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(NORMAL_FONT_SIZE); 1983146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextAlign(Paint.Align.LEFT); 1984146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint eventTextPaint = mEventTextPaint; 1985146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1986146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the background for the all-day events area 19873eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = DAY_HEADER_HEIGHT; 19883eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = r.top + mAllDayHeight + ALLDAY_TOP_MARGIN; 19893eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = mHoursWidth; 19903eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = r.left + mNumDays * (mCellWidth + DAY_GAP); 19913eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarAllDayBackground); 19923eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the extra space on the right side with the default background 19953eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = r.right; 19963eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mViewWidth; 19973eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 19983eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 1999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20003eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the outer vertical grid lines 2001d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarGridLineVerticalColor); 20029c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan p.setStyle(Style.FILL); 20033eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_WIDTH); 2004146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 20053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startY = DAY_HEADER_HEIGHT; 20063eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopY = startY + mAllDayHeight + ALLDAY_TOP_MARGIN; 20073eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaX = mCellWidth + DAY_GAP; 20081ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan float x = mHoursWidth; 200902041687c35441e8a21cb763f1fc3a26525292efDavid Brown int linesIndex = 0; 20101ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // Line bounding the top of the all day area 20111ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = 0; 20121ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 20131ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = mHoursWidth + deltaX * mNumDays; 20141ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 20151ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 20163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int day = 0; day < mNumDays; day++) { 20171ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x += deltaX; 201802041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 201902041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 202002041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 202102041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 2022146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 202302041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 20243eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 20253eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner vertical grid lines 20263eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerVerticalColor); 20271ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x = mHoursWidth; 20283eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 202902041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 20301ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // Line bounding the top of the all day area 20311ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = 0; 20321ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 20331ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = mHoursWidth + (deltaX) * mNumDays; 20341ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 20351ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 20363eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int day = 0; day < mNumDays; day++) { 20371ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x += deltaX; 203802041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 203902041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 204002041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 204102041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 20423eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 204302041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 20443eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 2045146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 2046146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setStyle(Style.FILL); 2047146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20483eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int y = DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 2049146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float left = mHoursWidth; 2050146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int lastDay = firstDay + numDays - 1; 205108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final ArrayList<Event> events = mAllDayEvents; 2052146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 2053146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float drawHeight = mAllDayHeight; 2054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float numRectangles = mMaxAllDayEvents; 2055146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 2056146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 2057146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startDay = event.startDay; 2058146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endDay = event.endDay; 2059c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (startDay > lastDay || endDay < firstDay) { 2060146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2061c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2062c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (startDay < firstDay) { 2063146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startDay = firstDay; 2064c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2065c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (endDay > lastDay) { 2066146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endDay = lastDay; 2067c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2068146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startIndex = startDay - firstDay; 2069146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endIndex = endDay - firstDay; 2070146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float height = drawHeight / numRectangles; 2071146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2072146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Prevent a single event from getting too big 2073f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan if (height > MAX_HEIGHT_OF_ONE_ALLDAY_EVENT) { 2074f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan height = MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 2075146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2076146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Leave a one-pixel space between the vertical day lines and the 2078146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event rectangle. 20799c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan event.left = left + startIndex * (mCellWidth + DAY_GAP); 20809c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan event.right = left + endIndex * (mCellWidth + DAY_GAP) + mCellWidth; 2081146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.top = y + height * event.getColumn(); 20829c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan event.bottom = event.top + height; 2083146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20841ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Rect r = drawEventRect(event, canvas, p, eventTextPaint); 20851ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan setupAllDayTextRect(r); 208608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = getEventLayout(mAllDayLayouts, i, event, eventTextPaint, r); 208708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan drawEventText(layout, r, canvas, r.top, r.bottom); 2088146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2089146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check if this all-day event intersects the selected day 2090146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay && mComputeSelectedEvents) { 2091146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (startDay <= mSelectionDay && endDay >= mSelectionDay) { 2092146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 2093146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2094146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2095146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2096146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2097146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay) { 2098146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the neighbors for the list of all-day events that 2099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // intersect the selected day. 2100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeAllDayNeighbors(); 2101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Set the selection position to zero so that when we move down 2103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // to the normal event area, we will highlight the topmost event. 2104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project saveSelectionPosition(0f, 0f, 0f, 0f); 2105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeAllDayNeighbors() { 2109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 2110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len == 0 || mSelectedEvent != null) { 2111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear all the links 2115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = null; 2118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = null; 2119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = null; 2120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = null; 2121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each event in the selected event list "mSelectedEvents", find 2124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // its neighbors in the up and down directions. This could be done 2125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // more efficiently by sorting on the Event.getColumn() field, but 2126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the list is expected to be very small. 2127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Find the event in the same row as the previously selected all-day 2129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event, if any. 2130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startPosition = -1; 2131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPrevSelectedEvent != null && mPrevSelectedEvent.allDay) { 2132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startPosition = mPrevSelectedEvent.getColumn(); 2133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxPosition = -1; 2135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event startEvent = null; 2136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event maxPositionEvent = null; 2137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int position = ev.getColumn(); 2140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (position == startPosition) { 2141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEvent = ev; 2142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (position > maxPosition) { 2143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxPositionEvent = ev; 2144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxPosition = position; 2145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int jj = 0; jj < len; jj++) { 2147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (jj == ii) { 2148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event neighbor = mSelectedEvents.get(jj); 2151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborPosition = neighbor.getColumn(); 2152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborPosition == position - 1) { 2153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = neighbor; 2154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborPosition == position + 1) { 2155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = neighbor; 2156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (startEvent != null) { 2160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = startEvent; 2161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = maxPositionEvent; 2163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawEvents(int date, int left, int top, Canvas canvas, Paint p) { 2167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint eventTextPaint = mEventTextPaint; 2168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellWidth = mCellWidth; 2169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellHeight = mCellHeight; 2170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use the selected hour as the selection region 2172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect selectionArea = mRect; 2173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.top = top + mSelectionHour * (cellHeight + HOUR_GAP); 2174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.bottom = selectionArea.top + cellHeight; 2175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.left = left; 2176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.right = selectionArea.left + cellWidth; 2177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 217808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final ArrayList<Event> events = mEvents; 2179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 2180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project EventGeometry geometry = mEventGeometry; 2181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 218208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final int viewEndY = mViewStartY + mViewHeight - DAY_HEADER_HEIGHT - mAllDayHeight; 2183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 2184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 2185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!geometry.computeEventRect(date, left, top, cellWidth, event)) { 2186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 218908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Don't draw it if it is not visible 219008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (event.bottom < mViewStartY || event.top > viewEndY) { 219108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan continue; 219208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 219308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 2194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (date == mSelectionDay && !mSelectionAllDay && mComputeSelectedEvents 2195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && geometry.eventIntersectsSelection(event, selectionArea)) { 2196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 2197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 21991ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Rect r = drawEventRect(event, canvas, p, eventTextPaint); 22001ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan setupTextRect(r); 220108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 220208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Don't draw text if it is not visible 220308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (r.top > viewEndY || r.bottom < mViewStartY) { 220408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan continue; 220508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 220608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = getEventLayout(mLayouts, i, event, eventTextPaint, r); 220708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // TODO: not sure why we are 4 pixels off 220808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan drawEventText(layout, r, canvas, mViewStartY + 4, 220908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mViewStartY + mViewHeight - DAY_HEADER_HEIGHT - mAllDayHeight); 2210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (date == mSelectionDay && !mSelectionAllDay && isFocused() 2213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && mSelectionMode != SELECTION_HIDDEN) { 2214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeNeighbors(); 2215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Computes the "nearest" neighbor event in four directions (left, right, 2219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // up, down) for each of the events in the mSelectedEvents array. 2220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeNeighbors() { 2221146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 2222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len == 0 || mSelectedEvent != null) { 2223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear all the links 2227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = null; 2230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = null; 2231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = null; 2232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = null; 2233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event startEvent = mSelectedEvents.get(0); 2236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startEventDistance1 = 100000; // any large number 2237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startEventDistance2 = 100000; // any large number 2238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevLocation = FROM_NONE; 2239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevTop; 2240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevBottom; 2241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevLeft; 2242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevRight; 2243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevCenter = 0; 2244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect box = getCurrentSelectionPosition(); 2245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPrevSelectedEvent != null) { 2246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = (int) mPrevSelectedEvent.top; 2247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = (int) mPrevSelectedEvent.bottom; 2248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = (int) mPrevSelectedEvent.left; 2249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = (int) mPrevSelectedEvent.right; 2250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check if the previously selected event intersects the previous 2251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // selection box. (The previously selected event may be from a 2252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // much older selection box.) 2253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevTop >= mPrevBox.bottom || prevBottom <= mPrevBox.top 2254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || prevRight <= mPrevBox.left || prevLeft >= mPrevBox.right) { 2255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 2256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 2257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 2258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = mPrevBox.left; 2259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = mPrevBox.right; 2260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Clip the top and bottom to the previous selection box. 2262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevTop < mPrevBox.top) { 2263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 2264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevBottom > mPrevBox.bottom) { 2266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 2267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Just use the previously drawn selection box 2271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 2272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 2273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = mPrevBox.left; 2274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = mPrevBox.right; 2275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out where we came from and compute the center of that area. 2278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevLeft >= box.right) { 2279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was to the right of us. 2280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_RIGHT; 2281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevTop + prevBottom) / 2; 2282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevRight <= box.left) { 2283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was to the left of us. 2284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_LEFT; 2285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevTop + prevBottom) / 2; 2286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevBottom <= box.top) { 2287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was above us. 2288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_ABOVE; 2289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevLeft + prevRight) / 2; 2290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevTop >= box.bottom) { 2291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was below us. 2292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_BELOW; 2293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevLeft + prevRight) / 2; 2294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each event in the selected event list "mSelectedEvents", search 2297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // all the other events in that list for the nearest neighbor in 4 2298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // directions. 2299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startTime = ev.startTime; 2303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endTime = ev.endTime; 2304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int left = (int) ev.left; 2305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int right = (int) ev.right; 2306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int top = (int) ev.top; 2307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (top < box.top) { 2308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project top = box.top; 2309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int bottom = (int) ev.bottom; 2311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom > box.bottom) { 2312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project bottom = box.bottom; 2313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (false) { 2315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL 2316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 2317ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (DateFormat.is24HourFormat(mContext)) { 2318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags |= DateUtils.FORMAT_24HOUR; 2319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2320ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan String timeRange = DateUtils.formatDateRange(mContext, 2321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.startMillis, ev.endMillis, flags); 2322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Log.i("Cal", "left: " + left + " right: " + right + " top: " + top 2323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project + " bottom: " + bottom + " ev: " + timeRange + " " + ev.title); 2324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int upDistanceMin = 10000; // any large number 2326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int downDistanceMin = 10000; // any large number 2327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int leftDistanceMin = 10000; // any large number 2328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int rightDistanceMin = 10000; // any large number 2329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event upEvent = null; 2330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event downEvent = null; 2331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event leftEvent = null; 2332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event rightEvent = null; 2333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the starting event closest to the previously selected event, 2335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // if any. distance1 takes precedence over distance2. 2336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance1 = 0; 2337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance2 = 0; 2338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevLocation == FROM_ABOVE) { 2339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (left >= prevCenter) { 2340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = left - prevCenter; 2341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (right <= prevCenter) { 2342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - right; 2343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = top - prevBottom; 2345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_BELOW) { 2346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (left >= prevCenter) { 2347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = left - prevCenter; 2348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (right <= prevCenter) { 2349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - right; 2350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = prevTop - bottom; 2352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_LEFT) { 2353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom <= prevCenter) { 2354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - bottom; 2355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (top >= prevCenter) { 2356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = top - prevCenter; 2357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = left - prevRight; 2359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_RIGHT) { 2360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom <= prevCenter) { 2361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - bottom; 2362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (top >= prevCenter) { 2363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = top - prevCenter; 2364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = prevLeft - right; 2366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance1 < startEventDistance1 2368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || (distance1 == startEventDistance1 && distance2 < startEventDistance2)) { 2369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEvent = ev; 2370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEventDistance1 = distance1; 2371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEventDistance2 = distance2; 2372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each neighbor, figure out if it is above or below or left 2375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // or right of me and compute the distance. 2376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int jj = 0; jj < len; jj++) { 2377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (jj == ii) { 2378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event neighbor = mSelectedEvents.get(jj); 2381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborLeft = (int) neighbor.left; 2382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborRight = (int) neighbor.right; 2383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighbor.endTime <= startTime) { 2384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely above me. 2385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we overlap the same column, then compute the distance. 2386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft < right && neighborRight > left) { 2387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = startTime - neighbor.endTime; 2388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < upDistanceMin) { 2389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upDistanceMin = distance; 2390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upEvent = neighbor; 2391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == upDistanceMin) { 2392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (left + right) / 2; 2393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = 0; 2394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentLeft = (int) upEvent.left; 2395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentRight = (int) upEvent.right; 2396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (currentRight <= center) { 2397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = center - currentRight; 2398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (currentLeft >= center) { 2399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = currentLeft - center; 2400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = 0; 2403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborRight <= center) { 2404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = center - neighborRight; 2405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborLeft >= center) { 2406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = neighborLeft - center; 2407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upDistanceMin = distance; 2410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upEvent = neighbor; 2411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighbor.startTime >= endTime) { 2415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely below me. 2416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we overlap the same column, then compute the distance. 2417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft < right && neighborRight > left) { 2418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = neighbor.startTime - endTime; 2419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < downDistanceMin) { 2420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downDistanceMin = distance; 2421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downEvent = neighbor; 2422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == downDistanceMin) { 2423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (left + right) / 2; 2424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = 0; 2425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentLeft = (int) downEvent.left; 2426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentRight = (int) downEvent.right; 2427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (currentRight <= center) { 2428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = center - currentRight; 2429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (currentLeft >= center) { 2430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = currentLeft - center; 2431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = 0; 2434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborRight <= center) { 2435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = center - neighborRight; 2436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborLeft >= center) { 2437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = neighborLeft - center; 2438146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downDistanceMin = distance; 2441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downEvent = neighbor; 2442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft >= right) { 2448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely to the right of me. 2449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Take the closest neighbor in the y direction. 2450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (top + bottom) / 2; 2451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = 0; 2452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborBottom = (int) neighbor.bottom; 2453146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborTop = (int) neighbor.top; 2454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborBottom <= center) { 2455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = center - neighborBottom; 2456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborTop >= center) { 2457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = neighborTop - center; 2458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < rightDistanceMin) { 2460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightDistanceMin = distance; 2461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightEvent = neighbor; 2462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == rightDistanceMin) { 2463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the closest in the x direction 2464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = neighborLeft - right; 2465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = (int) rightEvent.left - right; 2466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightDistanceMin = distance; 2468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightEvent = neighbor; 2469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborRight <= left) { 2472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely to the left of me. 2473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Take the closest neighbor in the y direction. 2474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (top + bottom) / 2; 2475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = 0; 2476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborBottom = (int) neighbor.bottom; 2477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborTop = (int) neighbor.top; 2478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborBottom <= center) { 2479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = center - neighborBottom; 2480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborTop >= center) { 2481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = neighborTop - center; 2482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < leftDistanceMin) { 2484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftDistanceMin = distance; 2485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftEvent = neighbor; 2486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == leftDistanceMin) { 2487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the closest in the x direction 2488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = left - neighborRight; 2489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = left - (int) leftEvent.right; 2490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 2491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftDistanceMin = distance; 2492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftEvent = neighbor; 2493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = upEvent; 2498146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = downEvent; 2499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = leftEvent; 2500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = rightEvent; 2501146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = startEvent; 2503146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2504146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 25051ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private Rect drawEventRect(Event event, Canvas canvas, Paint p, Paint eventTextPaint) { 250611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw the Event Rect 25071ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Rect r = mRect; 25081ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top = (int) event.top + EVENT_RECT_TOP_MARGIN; 25091ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = (int) event.bottom - EVENT_RECT_BOTTOM_MARGIN; 25101ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = (int) event.left + EVENT_RECT_LEFT_MARGIN; 25111ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = (int) event.right - EVENT_RECT_RIGHT_MARGIN; 25121ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 25131ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mEventBoxDrawable.setBounds(r); 25141ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mEventBoxDrawable.draw(canvas); 25151ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan// drawEmptyRect(canvas, r, 0xFF00FF00); // for debugging 2516146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 251711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan int eventTextColor = mEventTextColor; 25181ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setStyle(Style.FILL); 2519e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 2520146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If this event is selected, then use the selection color 2521146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == event) { 25221ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan boolean paintIt = false; 25231ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int color = 0; 2524146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_PRESSED) { 2525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 2526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 2527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // box = mBoxPressed; 252878f58c119af15ed85a727e16cddd793ced4c809dMichael Chan color = mPressedColor; 252911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan eventTextColor = mSelectedEventTextColor; 25301ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan paintIt = true; 2531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionMode == SELECTION_SELECTED) { 2532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 2533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 2534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // box = mBoxSelected; 253578f58c119af15ed85a727e16cddd793ced4c809dMichael Chan color = mPressedColor; 253611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan eventTextColor = mSelectedEventTextColor; 25371ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan paintIt = true; 2538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionMode == SELECTION_LONGPRESS) { 2539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // box = mBoxLongPressed; 254078f58c119af15ed85a727e16cddd793ced4c809dMichael Chan color = mPressedColor; 254111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan eventTextColor = mSelectedEventTextColor; 25421ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan paintIt = true; 25431ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan } 25441ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 25451ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (paintIt) { 25461ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setColor(color); 25471ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawRect(r, p); 2548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 255111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan eventTextPaint.setColor(eventTextColor); 255211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw cal color square border 25531ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top = (int) event.top + CALENDAR_COLOR_SQUARE_V_OFFSET; 25541ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = (int) event.left + CALENDAR_COLOR_SQUARE_H_OFFSET; 25551ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top + CALENDAR_COLOR_SQUARE_SIZE + 1; 25561ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = r.left + CALENDAR_COLOR_SQUARE_SIZE + 1; 255711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setColor(0xFFFFFFFF); 25581ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawRect(r, p); 25598af2529989a9b10a0bb84736695c22fc02a17a4aThe Android Open Source Project 256011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw cal color 25611ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top++; 25621ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left++; 25631ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom--; 25641ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right--; 256511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setColor(event.color); 25661ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawRect(r, p); 2567e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 256811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan boolean declined = (event.selfAttendeeStatus == Attendees.ATTENDEE_STATUS_DECLINED); 256911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan if (declined) { 257011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan boolean aa = p.isAntiAlias(); 257111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan if (!aa) { 257211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setAntiAlias(true); 257311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan } 257411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Temp behavior 257511ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setColor(0x88FFFFFF); 25761ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawLine(r.right, r.top, r.left, r.bottom, p); 257711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan if (!aa) { 257811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan p.setAntiAlias(false); 257911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan } 258011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan } 258111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan 25823eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Setup rect for drawEventText which follows 25831ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top = (int) event.top + EVENT_RECT_TOP_MARGIN; 25841ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = (int) event.bottom - EVENT_RECT_BOTTOM_MARGIN; 25851ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = (int) event.left + EVENT_RECT_LEFT_MARGIN; 25861ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = (int) event.right - EVENT_RECT_RIGHT_MARGIN; 25871ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan return r; 2588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 25900d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan private Pattern drawTextSanitizerFilter = Pattern.compile("[\t\n],"); 25910d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 25920d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // Sanitize a string before passing it to drawText or else we get little 25930d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // squares. For newlines and tabs before a comma, delete the character. 25940d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // Otherwise, just replace them with a space. 2595f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan private String drawTextSanitizer(String string, int maxEventTextLen) { 25960d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan Matcher m = drawTextSanitizerFilter.matcher(string); 2597f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan string = m.replaceAll(","); 2598f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan 2599f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan int len = string.length(); 2600f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan if (len > maxEventTextLen) { 2601f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan string = string.substring(0, maxEventTextLen); 2602f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan len = maxEventTextLen; 2603f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan } 2604f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan 2605f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan return string.replace('\n', ' '); 26060d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan } 26070d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 260808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private void drawEventText(StaticLayout eventLayout, Rect rect, Canvas canvas, int top, 260908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan int bottom) { 26101ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // drawEmptyRect(canvas, rect, 0xFFFF00FF); // for debugging 26111ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 26121ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int width = rect.right - rect.left; 26131ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int height = rect.bottom - rect.top; 2614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the rectangle is too small for text, then return 26160a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan if (eventLayout == null || width < MIN_CELL_WIDTH_FOR_TEXT) { 2617f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan return; 2618f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 2619f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan 262008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan int totalLineHeight = 0; 2621f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan int lineCount = eventLayout.getLineCount(); 2622f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan for (int i = 0; i < lineCount; i++) { 2623f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan int lineBottom = eventLayout.getLineBottom(i); 2624f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan if (lineBottom <= height) { 262508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan totalLineHeight = lineBottom; 262608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 262708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan break; 2628f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 2629f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 2630f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan 263108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (totalLineHeight == 0 || rect.top > bottom || rect.top + totalLineHeight < top) { 2632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 26353e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh // Use a StaticLayout to format the string. 26363e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh canvas.save(); 26371ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.translate(rect.left, rect.top); 26381ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.left = 0; 26391ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.right = width; 26401ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.top = 0; 264108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan rect.bottom = totalLineHeight; 264208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 264308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // There's a bug somewhere. If this rect is outside of a previous 264408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // cliprect, this becomes a no-op. What happens is that the text draw 264508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // past the event rect. The current fix is to not draw the staticLayout 264608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // at all if it is completely out of bound. 26471ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.clipRect(rect); 26483e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh eventLayout.draw(canvas); 26493e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh canvas.restore(); 2650146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 26521ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // This is to replace p.setStyle(Style.STROKE); canvas.drawRect() since it 26531ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // doesn't work well with hardware acceleration 26541ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void drawEmptyRect(Canvas canvas, Rect r, int color) { 26551ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int linesIndex = 0; 26561ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.left; 26571ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.top; 26581ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.right; 26591ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.top; 26601ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 26611ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.left; 26621ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.bottom; 26631ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.right; 26641ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.bottom; 26651ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 26661ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.left; 26671ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.top; 26681ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.left; 26691ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.bottom; 26701ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 26711ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.right; 26721ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.top; 26731ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.right; 26741ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = r.bottom; 26751ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mPaint.setColor(color); 26761ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawLines(mLines, 0, linesIndex, mPaint); 26771ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan } 26781ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 2679146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void updateEventDetails() { 2680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null || mSelectionMode == SELECTION_HIDDEN 2681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || mSelectionMode == SELECTION_LONGPRESS) { 2682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 2683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2685666fc5e8ddbac15c951aad738bd818ee307eae42Erik if (mLastPopupEventID == mSelectedEvent.id) { 2686666fc5e8ddbac15c951aad738bd818ee307eae42Erik return; 2687666fc5e8ddbac15c951aad738bd818ee307eae42Erik } 2688666fc5e8ddbac15c951aad738bd818ee307eae42Erik 2689666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = mSelectedEvent.id; 2690146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2691146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Remove any outstanding callbacks to dismiss the popup. 2692146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getHandler().removeCallbacks(mDismissPopup); 2693146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2694146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = mSelectedEvent; 2695146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView titleView = (TextView) mPopupView.findViewById(R.id.event_title); 2696146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project titleView.setText(event.title); 2697146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2698146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ImageView imageView = (ImageView) mPopupView.findViewById(R.id.reminder_icon); 2699146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView.setVisibility(event.hasAlarm ? View.VISIBLE : View.GONE); 2700146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2701146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView = (ImageView) mPopupView.findViewById(R.id.repeat_icon); 2702146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView.setVisibility(event.isRepeating ? View.VISIBLE : View.GONE); 2703146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2704146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags; 2705146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.allDay) { 2706146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags = DateUtils.FORMAT_UTC | DateUtils.FORMAT_SHOW_DATE | 2707146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_ALL; 2708146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2709146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE 2710146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_ALL 2711146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 2712146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2713ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (DateFormat.is24HourFormat(mContext)) { 2714146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags |= DateUtils.FORMAT_24HOUR; 2715146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2716731f1cb808b7586b93615b408ab2636081fab0dcErik String timeRange = Utils.formatDateRange(mContext, 2717146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startMillis, event.endMillis, flags); 2718146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView timeView = (TextView) mPopupView.findViewById(R.id.time); 2719146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project timeView.setText(timeRange); 2720146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2721146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView whereView = (TextView) mPopupView.findViewById(R.id.where); 2722146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final boolean empty = TextUtils.isEmpty(event.location); 2723146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project whereView.setVisibility(empty ? View.GONE : View.VISIBLE); 2724146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!empty) whereView.setText(event.location); 2725146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2726146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.showAtLocation(this, Gravity.BOTTOM | Gravity.LEFT, mHoursWidth, 5); 2727146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project postDelayed(mDismissPopup, POPUP_DISMISS_DELAY); 2728146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2729146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2730146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The following routines are called from the parent activity when certain 2731146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // touch events occur. 27324484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doDown(MotionEvent ev) { 2733146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_DOWN; 2734146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = 0; 2735146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mOnFlingCalled = false; 2736146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getHandler().removeCallbacks(mContinueScroll); 2737146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2738146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 27394484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doSingleTapUp(MotionEvent ev) { 2740d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (!mHandleActionUp) { 2741d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return; 2742d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2743d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2744146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int x = (int) ev.getX(); 2745146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = (int) ev.getY(); 2746146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectedDay = mSelectionDay; 2747146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectedHour = mSelectionHour; 2748146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2749146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean validPosition = setSelectionFromPosition(x, y); 2750146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!validPosition) { 275180bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan // return if the touch wasn't on an area of concern 2752146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2753146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2754146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 275580bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan mSelectionMode = SELECTION_SELECTED; 2756146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 2757146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 275880bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan if (mSelectedEvent != null) { 275980bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan // If the tap is on an event, launch the "View event" view 2760344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, mSelectedEvent.id, 2761344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mSelectedEvent.startMillis, mSelectedEvent.endMillis, (int) ev.getRawX(), 2762344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan (int) ev.getRawY()); 2763344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan } else if (selectedDay == mSelectionDay && selectedHour == mSelectionHour) { 2764344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan // If the tap is on an already selected hour slot, then create a new 2765344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan // event 2766344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 2767344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan getSelectedTimeInMillis(), 0, (int) ev.getRawX(), (int) ev.getRawY()); 2768344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan } else { 2769344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan Time startTime = new Time(mBaseDate); 2770344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.setJulianDay(mSelectionDay); 2771344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.hour = mSelectionHour; 2772344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.normalize(true /* ignore isDst */); 277383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 277483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time endTime = new Time(startTime); 277583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan endTime.hour++; 277683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 2777344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan mController.sendEvent(this, EventType.GO_TO, startTime, endTime, -1, ViewType.CURRENT); 2778146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2779146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2780146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 27814484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doLongPress(MotionEvent ev) { 2782d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // Scale gesture in progress 2783d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mStartingSpanY != 0) { 2784d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return; 2785d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2786d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 278780bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan int x = (int) ev.getX(); 278880bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan int y = (int) ev.getY(); 278980bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan 279080bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan boolean validPosition = setSelectionFromPosition(x, y); 279180bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan if (!validPosition) { 279280bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan // return if the touch wasn't on an area of concern 279380bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan return; 279480bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan } 279580bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan 2796146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 2797146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 2798146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project performLongClick(); 2799146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2800146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 28014484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doScroll(MotionEvent e1, MotionEvent e2, float deltaX, float deltaY) { 2802146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use the distance from the current point to the initial touch instead 2803146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // of deltaX and deltaY to avoid accumulating floating-point rounding 2804146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // errors. Also, we don't need floats, we can use ints. 2805146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceX = (int) e1.getX() - (int) e2.getX(); 2806146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceY = (int) e1.getY() - (int) e2.getY(); 2807146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2808146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we haven't figured out the predominant scroll direction yet, 2809146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // then do it now. 2810146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mTouchMode == TOUCH_MODE_DOWN) { 2811146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int absDistanceX = Math.abs(distanceX); 2812146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int absDistanceY = Math.abs(distanceY); 2813146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrollStartY = mViewStartY; 2814146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPreviousDirection = 0; 2815146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2816146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the x distance is at least twice the y distance, then lock 2817146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the scroll horizontally. Otherwise scroll vertically. 2818146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (absDistanceX >= 2 * absDistanceY) { 2819146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_HSCROLL; 2820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = distanceX; 2821146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initNextView(-mViewStartX); 2822146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2823146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_VSCROLL; 2824146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2825146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 2826146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We are already scrolling horizontally, so check if we 2827146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // changed the direction of scrolling so that the other week 2828146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // is now visible. 2829146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = distanceX; 2830146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distanceX != 0) { 2831146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int direction = (distanceX > 0) ? 1 : -1; 2832146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (direction != mPreviousDirection) { 2833146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The user has switched the direction of scrolling 2834146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // so re-init the next view 2835146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initNextView(-mViewStartX); 2836146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPreviousDirection = direction; 2837146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_VSCROLL) != 0) { 2842146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mScrollStartY + distanceY; 2843146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 2844146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 2845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mViewStartY > mMaxViewStartY) { 2846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mMaxViewStartY; 2847146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2848146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeFirstHour(); 2849146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2850146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2851146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = true; 2852146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2853d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan mSelectionMode = SELECTION_HIDDEN; 2854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 2855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 28574484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 2858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_INITIAL_STATE; 2859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_HIDDEN; 2860146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mOnFlingCalled = true; 2861146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaX = (int) e2.getX() - (int) e1.getX(); 2862146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceX = Math.abs(deltaX); 2863146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int deltaY = (int) e2.getY() - (int) e1.getY(); 2864146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distanceY = Math.abs(deltaY); 2865030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "doFling: distanceX " + distanceX 2866d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan + ", HORIZONTAL_FLING_THRESHOLD " + HORIZONTAL_FLING_THRESHOLD); 2867146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2868d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan if ((distanceX >= HORIZONTAL_FLING_THRESHOLD) && (distanceX > distanceY)) { 2869030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown // Horizontal fling. 287011638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // initNextView(deltaX); 2871d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan switchViews(deltaX < 0, mViewStartX, mViewWidth); 2872146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = 0; 2873146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2874146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2875146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2876030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown // Vertical fling. 2877030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown mViewStartX = 0; 2878030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown 2879146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Continue scrolling vertically 2880146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mContinueScroll.init((int) velocityY / 20); 2881146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project post(mContinueScroll); 2882146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2883146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2884146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean initNextView(int deltaX) { 2885146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Change the view to the previous day or week 2886d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getNextView(); 2887146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time date = view.mBaseDate; 2888146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.set(mBaseDate); 2889146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean switchForward; 2890146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (deltaX > 0) { 2891146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay -= mNumDays; 2892146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = mSelectionDay - mNumDays; 2893146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchForward = false; 2894146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2895146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay += mNumDays; 2896146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = mSelectionDay + mNumDays; 2897146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchForward = true; 2898146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2899146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.normalize(true /* ignore isDst */); 2900146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initView(view); 2901ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan view.layout(getLeft(), getTop(), getRight(), getBottom()); 2902146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.reloadEvents(); 2903146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return switchForward; 2904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2905146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2906d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 2907d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public boolean onScaleBegin(ScaleGestureDetector detector) { 2908d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = false; 2909d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float gestureCenterInPixels = detector.getFocusY() - DAY_HEADER_HEIGHT - mAllDayHeight; 2910d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) / (mCellHeight + DAY_GAP); 2911d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2912d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = Math.max(MIN_Y_SPAN, Math.abs(detector.getCurrentSpanY())); 2913d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = mCellHeight; 2914d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2915d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 2916d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float ViewStartHour = mViewStartY / (float) (mCellHeight + DAY_GAP); 2917d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.d(TAG, "mGestureCenterHour:" + mGestureCenterHour + "\tViewStartHour: " 2918d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + ViewStartHour + "\tmViewStartY:" + mViewStartY + "\tmCellHeight:" 2919d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + mCellHeight); 2920d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2921d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2922d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 2923d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2924d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2925d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 2926d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public boolean onScale(ScaleGestureDetector detector) { 2927d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float spanY = Math.abs(detector.getCurrentSpanY()); 2928d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2929d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = (int) (mCellHeightBeforeScaleGesture * spanY / mStartingSpanY); 2930d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2931d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight < mMinCellHeight) { 2932d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // If mStartingSpanY is too small, even a small increase in the 2933d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // gesture can bump the mCellHeight beyond MAX_CELL_HEIGHT 2934d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = Math.max(MIN_Y_SPAN, spanY); 2935d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = mMinCellHeight; 2936d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = mMinCellHeight; 2937d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } else if (mCellHeight > MAX_CELL_HEIGHT) { 2938d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = spanY; 2939d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = MAX_CELL_HEIGHT; 2940d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = MAX_CELL_HEIGHT; 2941d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2942d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2943d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan int gestureCenterInPixels = (int) detector.getFocusY() - DAY_HEADER_HEIGHT - mAllDayHeight; 2944d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = (int) (mGestureCenterHour * (mCellHeight + DAY_GAP)) - gestureCenterInPixels; 2945d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mMaxViewStartY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP) - mGridAreaHeight; 2946d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2947d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 2948d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float ViewStartHour = mViewStartY / (float) (mCellHeight + DAY_GAP); 2949d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.d(TAG, " mGestureCenterHour:" + mGestureCenterHour + "\tViewStartHour: " 2950d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + ViewStartHour + "\tmViewStartY:" + mViewStartY + "\tmCellHeight:" 2951d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + mCellHeight + " SpanY:" + detector.getCurrentSpanY()); 2952d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2953d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2954d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mViewStartY < 0) { 2955d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = 0; 2956d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) 2957d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan / (float) (mCellHeight + DAY_GAP); 2958d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } else if (mViewStartY > mMaxViewStartY) { 2959d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = mMaxViewStartY; 2960d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) 2961d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan / (float) (mCellHeight + DAY_GAP); 2962d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2963d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan computeFirstHour(); 2964d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2965d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mRemeasure = true; 2966d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan invalidate(); 2967d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 2968d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2969d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2970d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 2971d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public void onScaleEnd(ScaleGestureDetector detector) { 2972d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = 0; 2973d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2974d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2975146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 2976146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onTouchEvent(MotionEvent ev) { 2977146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int action = ev.getAction(); 2978146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 29791ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan if ((mTouchMode & TOUCH_MODE_HSCROLL) == 0) { 29801ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan mScaleGestureDetector.onTouchEvent(ev); 29811ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan if (mScaleGestureDetector.isInProgress()) { 29821ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan return true; 29831ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan } 2984d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 2985d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 2986146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (action) { 2987146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case MotionEvent.ACTION_DOWN: 2988d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) Log.e(TAG, "ACTION_DOWN"); 2989d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = true; 2990ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector.onTouchEvent(ev); 2991146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 2992146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case MotionEvent.ACTION_MOVE: 2994d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) Log.e(TAG, "ACTION_MOVE"); 2995ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector.onTouchEvent(ev); 2996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 2997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2998146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case MotionEvent.ACTION_UP: 2999d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) Log.e(TAG, "ACTION_UP " + mHandleActionUp); 3000ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector.onTouchEvent(ev); 3001d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (!mHandleActionUp) { 3002d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = true; 3003d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 3004d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3005146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mOnFlingCalled) { 3006146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 3007146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3008146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 3009146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_INITIAL_STATE; 3010d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan if (Math.abs(mViewStartX) > mHorizontalSnapBackThreshold) { 3011146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The user has gone beyond the threshold so switch views 3012030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "- horizontal scroll: switch views"); 3013ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan switchViews(mViewStartX > 0, mViewStartX, mViewWidth); 30147abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project mViewStartX = 0; 30157abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project return true; 3016146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3017146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Not beyond the threshold so invalidate which will cause 3018146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the view to snap back. Also call recalc() to ensure 3019146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // that we have the correct starting date and title. 3020030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "- horizontal scroll: snap back"); 3021146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 3022146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 30237abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project mViewStartX = 0; 3024146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3025146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3026146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3027146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we were scrolling, then reset the selected hour so that it 3028146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // is visible. 3029146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mScrolling) { 3030146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 3031146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project resetSelectedHour(); 3032146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3033146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3034146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 3035146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3036146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This case isn't expected to happen. 3037146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case MotionEvent.ACTION_CANCEL: 3038d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) Log.e(TAG, "ACTION_CANCEL"); 3039ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector.onTouchEvent(ev); 3040146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 3041146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project resetSelectedHour(); 3042146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 3043146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3044146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project default: 3045d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) Log.e(TAG, "Not MotionEvent"); 3046ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (mGestureDetector.onTouchEvent(ev)) { 3047146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 3048146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3049146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onTouchEvent(ev); 3050146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3051146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3052146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3053146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { 3054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project MenuItem item; 3055146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3056146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the trackball is held down, then the context menu pops up and 3057146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // we never get onKeyUp() for the long-press. So check for it here 3058146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // and change the selection to the long-press state. 3059146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode != SELECTION_LONGPRESS) { 3060146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 3061146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3062146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3063146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3064e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan final long startMillis = getSelectedTimeInMillis(); 3065146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags = DateUtils.FORMAT_SHOW_TIME 3066146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT 3067146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_SHOW_WEEKDAY; 3068c5f92d7bdeb1950ace783cc022aa41a4b4f00cd6Erik final String title = Utils.formatDateRange(mContext, startMillis, startMillis, flags); 3069146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project menu.setHeaderTitle(title); 3070e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3071146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numSelectedEvents = mSelectedEvents.size(); 3072146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 1) { 3073146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Day view. 3074146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3075146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is a selected event, then allow it to be viewed and 3076146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // edited. 3077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (numSelectedEvents >= 1) { 30784484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_VIEW, 0, R.string.event_view); 3079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3080146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_info_details); 3081146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3082ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan int accessLevel = getEventAccessLevel(mContext, mSelectedEvent); 3083a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel == ACCESS_LEVEL_EDIT) { 30844484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_EDIT, 0, R.string.event_edit); 3085146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3086146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_edit); 3087146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('e'); 3088a505627659f6bfba8869eac8089f7030f2d0d92cErik } 3089146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3090a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel >= ACCESS_LEVEL_DELETE) { 30914484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_DELETE, 0, R.string.event_delete); 3092146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3093146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_delete); 3094146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3095146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 30964484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 3097146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3098146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_add); 3099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('n'); 3100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Otherwise, if the user long-pressed on a blank hour, allow 3102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // them to create an event. They can also do this by tapping. 31034484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 3104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_add); 3106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('n'); 3107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Week view. 3110e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is a selected event, then allow it to be viewed and 3112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // edited. 3113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (numSelectedEvents >= 1) { 31144484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_VIEW, 0, R.string.event_view); 3115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_info_details); 3117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3118ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan int accessLevel = getEventAccessLevel(mContext, mSelectedEvent); 3119a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel == ACCESS_LEVEL_EDIT) { 31204484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_EDIT, 0, R.string.event_edit); 3121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_edit); 3123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('e'); 3124a505627659f6bfba8869eac8089f7030f2d0d92cErik } 3125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3126a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel >= ACCESS_LEVEL_DELETE) { 31274484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_DELETE, 0, R.string.event_delete); 3128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 3129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_delete); 3130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31314484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan } 3132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 31334484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 31344484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 31354484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_add); 31364484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('n'); 3137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 31384484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_DAY, 0, R.string.show_day_view); 31394484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 31404484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_day); 31414484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('d'); 3142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private class ContextMenuHandler implements MenuItem.OnMenuItemClickListener { 3148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onMenuItemClick(MenuItem item) { 3149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (item.getItemId()) { 31504484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_VIEW: { 3151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 3152a7694eead7cbb293990bc89c3906e17bad36194cErik mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT_DETAILS, 31539e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.id, mSelectedEvent.startMillis, 31549e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.endMillis, 0, 0); 3155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31584484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_EDIT: { 3159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 31609e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.EDIT_EVENT, 31619e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.id, mSelectedEvent.startMillis, 31629e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.endMillis, 0, 0); 3163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31664484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_DAY: { 3167487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mController.sendEvent(this, EventType.GO_TO, getSelectedTime(), null, -1, 31689e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan ViewType.DAY); 3169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31714484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_AGENDA: { 3172487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mController.sendEvent(this, EventType.GO_TO, getSelectedTime(), null, -1, 31739e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan ViewType.AGENDA); 3174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31764484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_CREATE: { 3177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 3178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 31799e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 31809e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan startMillis, endMillis, 0, 0); 3181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31834484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_DELETE: { 3184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 3185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 3186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long begin = selectedEvent.startMillis; 3187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long end = selectedEvent.endMillis; 3188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long id = selectedEvent.id; 31899e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.DELETE_EVENT, id, begin, 31909e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan end, 0, 0); 3191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project default: { 3195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return false; 3196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 3199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3202a505627659f6bfba8869eac8089f7030f2d0d92cErik private static int getEventAccessLevel(Context context, Event e) { 3203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ContentResolver cr = context.getContentResolver(); 3204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int visibility = Calendars.NO_ACCESS; 3206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Get the calendar id for this event 3208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Cursor cursor = cr.query(ContentUris.withAppendedId(Events.CONTENT_URI, e.id), 3209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project new String[] { Events.CALENDAR_ID }, 3210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* selection */, 3211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* selectionArgs */, 3212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* sort */); 3213e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3214e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan if (cursor == null) { 3215a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 3216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3217e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3218e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan if (cursor.getCount() == 0) { 3219e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan cursor.close(); 3220a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 3221e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan } 3222e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.moveToFirst(); 3224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long calId = cursor.getLong(0); 3225697bd6a8cec36cc75c72603674e57e4c6fe42dbfKen Shirriff cursor.close(); 3226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Uri uri = Calendars.CONTENT_URI; 3228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String where = String.format(CALENDARS_WHERE, calId); 3229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor = cr.query(uri, CALENDARS_PROJECTION, where, null, null); 3230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 32316d34cec523930368976bc8d358d0a6de1da3462cMichael Chan String calendarOwnerAccount = null; 3232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (cursor != null) { 3233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.moveToFirst(); 3234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project visibility = cursor.getInt(CALENDARS_INDEX_ACCESS_LEVEL); 32356d34cec523930368976bc8d358d0a6de1da3462cMichael Chan calendarOwnerAccount = cursor.getString(CALENDARS_INDEX_OWNER_ACCOUNT); 3236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.close(); 3237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3238e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 32396d34cec523930368976bc8d358d0a6de1da3462cMichael Chan if (visibility < Calendars.CONTRIBUTOR_ACCESS) { 3240a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 32416d34cec523930368976bc8d358d0a6de1da3462cMichael Chan } 3242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 32436d34cec523930368976bc8d358d0a6de1da3462cMichael Chan if (e.guestsCanModify) { 3244a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_EDIT; 3245a505627659f6bfba8869eac8089f7030f2d0d92cErik } 3246a505627659f6bfba8869eac8089f7030f2d0d92cErik 3247a505627659f6bfba8869eac8089f7030f2d0d92cErik if (!TextUtils.isEmpty(calendarOwnerAccount) && 3248a505627659f6bfba8869eac8089f7030f2d0d92cErik calendarOwnerAccount.equalsIgnoreCase(e.organizer)) { 3249a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_EDIT; 3250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3252a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_DELETE; 3253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Sets mSelectionDay and mSelectionHour based on the (x,y) touch position. 3257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * If the touch position is not within the displayed grid, then this 3258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * method returns false. 3259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 3260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param x the x position of the touch 3261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param y the y position of the touch 3262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return true if the touch position is valid 3263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 3264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean setSelectionFromPosition(int x, int y) { 3265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (x < mHoursWidth) { 3266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return false; 3267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int day = (x - mHoursWidth) / (mCellWidth + DAY_GAP); 3270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (day >= mNumDays) { 3271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project day = mNumDays - 1; 3272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project day += mFirstJulianDay; 3274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int hour; 3275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (y < mFirstCell + mFirstHourOffset) { 3276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = true; 3277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project hour = (y - mFirstCell - mFirstHourOffset) / (mCellHeight + HOUR_GAP); 3279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project hour += mFirstHour; 3280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = hour; 3281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionAllDay = false; 3282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = day; 3284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project findSelectedEvent(x, y); 3285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", "setSelectionFromPosition( " + x + ", " + y + " ) day: " + day 3286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// + " hour: " + hour 3287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// + " mFirstCell: " + mFirstCell + " mFirstHourOffset: " + mFirstHourOffset); 3288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// if (mSelectedEvent != null) { 3289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", " num events: " + mSelectedEvents.size() + " event: " + mSelectedEvent.title); 3290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// for (Event ev : mSelectedEvents) { 3291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL 3292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 3293ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// String timeRange = formatDateRange(mContext, 3294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// ev.startMillis, ev.endMillis, flags); 3295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// 3296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", " " + timeRange + " " + ev.title); 3297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// } 3298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// } 3299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 3300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void findSelectedEvent(int x, int y) { 3303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int date = mSelectionDay; 3304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellWidth = mCellWidth; 330508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final ArrayList<Event> events = mEvents; 3306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 3307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int left = mHoursWidth + (mSelectionDay - mFirstJulianDay) * (cellWidth + DAY_GAP); 3308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int top = 0; 3309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 3310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 3312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionAllDay) { 3313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float yDistance; 3314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float minYdistance = 10000.0f; // any large number 3315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event closestEvent = null; 3316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float drawHeight = mAllDayHeight; 33173eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int yOffset = DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 3318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 3319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 3320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!event.allDay) { 3321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.startDay <= mSelectionDay && event.endDay >= mSelectionDay) { 3325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float numRectangles = event.getMaxColumns(); 3326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float height = drawHeight / numRectangles; 3327f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan if (height > MAX_HEIGHT_OF_ONE_ALLDAY_EVENT) { 3328f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan height = MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 3329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float eventTop = yOffset + height * event.getColumn(); 3331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float eventBottom = eventTop + height; 3332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (eventTop < y && eventBottom > y) { 3333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the touch is inside the event rectangle, then 3334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // add the event. 3335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 3336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = event; 3337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 3338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Find the closest event 3340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (eventTop >= y) { 3341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project yDistance = eventTop - y; 3342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project yDistance = y - eventBottom; 3344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (yDistance < minYdistance) { 3346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project minYdistance = yDistance; 3347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = event; 3348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = closestEvent; 3353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Adjust y for the scrollable bitmap 3357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += mViewStartY - mFirstCell; 3358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use a region around (x,y) for the selection region 3360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect region = mRect; 3361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.left = x - 10; 3362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.right = x + 10; 3363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.top = y - 10; 3364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.bottom = y + 10; 3365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project EventGeometry geometry = mEventGeometry; 3367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 3369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 3370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the event rectangle. 3371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!geometry.computeEventRect(date, left, top, cellWidth, event)) { 3372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the event intersects the selection region, then add it to 3376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // mSelectedEvents. 3377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (geometry.eventIntersectsSelection(event, region)) { 3378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 3379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there are any events in the selected region, then assign the 3383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // closest one to mSelectedEvent. 3384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvents.size() > 0) { 3385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 3386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event closestEvent = null; 3387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float minDist = mViewWidth + mViewHeight; // some large distance 3388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int index = 0; index < len; index++) { 3389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(index); 3390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float dist = geometry.pointToEvent(x, y, ev); 3391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (dist < minDist) { 3392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project minDist = dist; 3393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = ev; 3394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = closestEvent; 3397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Keep the selected hour and day consistent with the selected 3399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event. They could be different if we touched on an empty hour 3400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // slot very close to an event in the previous hour slot. In 3401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // that case we will select the nearby event. 3402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startDay = mSelectedEvent.startDay; 3403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endDay = mSelectedEvent.endDay; 3404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionDay < startDay) { 3405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = startDay; 3406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionDay > endDay) { 3407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = endDay; 3408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startHour = mSelectedEvent.startTime / 60; 3411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endHour; 3412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent.startTime < mSelectedEvent.endTime) { 3413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endHour = (mSelectedEvent.endTime - 1) / 60; 3414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endHour = mSelectedEvent.endTime / 60; 3416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < startHour) { 3419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = startHour; 3420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionHour > endHour) { 3421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = endHour; 3422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Encapsulates the code to continue the scrolling after the 3427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // finger is lifted. Instead of stopping the scroll immediately, 3428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the scroll continues to "free spin" and gradually slows down. 3429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private class ContinueScroll implements Runnable { 3430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int mSignDeltaY; 3431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int mAbsDeltaY; 3432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float mFloatDeltaY; 3433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long mFreeSpinTime; 3434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final float FRICTION_COEF = 0.7F; 3435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final long FREE_SPIN_MILLIS = 180; 3436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int MAX_DELTA = 60; 3437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SCROLL_REPEAT_INTERVAL = 30; 3438146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void init(int deltaY) { 3440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSignDeltaY = 0; 3441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (deltaY > 0) { 3442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSignDeltaY = 1; 3443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (deltaY < 0) { 3444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSignDeltaY = -1; 3445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = Math.abs(deltaY); 3447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Limit the maximum speed 3449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY > MAX_DELTA) { 3450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = MAX_DELTA; 3451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFloatDeltaY = mAbsDeltaY; 3453146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFreeSpinTime = System.currentTimeMillis() + FREE_SPIN_MILLIS; 3454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", "init scroll: mAbsDeltaY: " + mAbsDeltaY 3455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// + " mViewStartY: " + mViewStartY); 3456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 3459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long time = System.currentTimeMillis(); 3460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Start out with a frictionless "free spin" 3462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (time > mFreeSpinTime) { 3463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the delta is small, then apply a fixed deceleration. 3464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Otherwise 3465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY <= 10) { 3466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY -= 2; 3467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFloatDeltaY *= FRICTION_COEF; 3469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = (int) mFloatDeltaY; 3470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY < 0) { 3473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = 0; 3474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSignDeltaY == 1) { 3478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY -= mAbsDeltaY; 3479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY += mAbsDeltaY; 3481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", " scroll: mAbsDeltaY: " + mAbsDeltaY 3483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// + " mViewStartY: " + mViewStartY); 3484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 3486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 3487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = 0; 3488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mViewStartY > mMaxViewStartY) { 3489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mMaxViewStartY; 3490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mAbsDeltaY = 0; 3491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeFirstHour(); 3494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mAbsDeltaY > 0) { 3496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project postDelayed(this, SCROLL_REPEAT_INTERVAL); 3497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3498146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Done scrolling. 3499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 3500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project resetSelectedHour(); 3501146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3503146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3504146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3505146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3506146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 3508bd0e834aea317236d574f8738fe11a51fdc87968Erik * Cleanup the pop-up and timers. 3509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 3510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void cleanup() { 3511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against null-pointer exceptions 3512146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPopup != null) { 3513146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3514146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3515666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 3516146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Handler handler = getHandler(); 3517146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (handler != null) { 3518146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project handler.removeCallbacks(mDismissPopup); 3519bd0e834aea317236d574f8738fe11a51fdc87968Erik handler.removeCallbacks(mUpdateCurrentTime); 3520146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3521e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3522d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Utils.setSharedPreference(mContext, GeneralPreferences.KEY_DEFAULT_CELL_HEIGHT, 3523d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight); 3524d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 35257abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project // Turn off redraw 35267abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project mRemeasure = false; 3527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3529bd0e834aea317236d574f8738fe11a51fdc87968Erik /** 3530bd0e834aea317236d574f8738fe11a51fdc87968Erik * Restart the update timer 3531bd0e834aea317236d574f8738fe11a51fdc87968Erik */ 3532bd0e834aea317236d574f8738fe11a51fdc87968Erik public void restartCurrentTimeUpdates() { 3533bd0e834aea317236d574f8738fe11a51fdc87968Erik post(mUpdateCurrentTime); 3534bd0e834aea317236d574f8738fe11a51fdc87968Erik } 3535bd0e834aea317236d574f8738fe11a51fdc87968Erik 3536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override protected void onDetachedFromWindow() { 3537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cleanup(); 3538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project super.onDetachedFromWindow(); 3539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project class DismissPopup implements Runnable { 3542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 3543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against null-pointer exceptions 3544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPopup != null) { 3545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3546146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3549bd0e834aea317236d574f8738fe11a51fdc87968Erik 3550bd0e834aea317236d574f8738fe11a51fdc87968Erik class UpdateCurrentTime implements Runnable { 3551bd0e834aea317236d574f8738fe11a51fdc87968Erik public void run() { 3552bd0e834aea317236d574f8738fe11a51fdc87968Erik long currentTime = System.currentTimeMillis(); 3553bd0e834aea317236d574f8738fe11a51fdc87968Erik mCurrentTime.set(currentTime); 3554bd0e834aea317236d574f8738fe11a51fdc87968Erik //% causes update to occur on 5 minute marks (11:10, 11:15, 11:20, etc.) 3555bd0e834aea317236d574f8738fe11a51fdc87968Erik postDelayed(mUpdateCurrentTime, 3556bd0e834aea317236d574f8738fe11a51fdc87968Erik UPDATE_CURRENT_TIME_DELAY - (currentTime % UPDATE_CURRENT_TIME_DELAY)); 3557bd0e834aea317236d574f8738fe11a51fdc87968Erik mTodayJulianDay = Time.getJulianDay(currentTime, mCurrentTime.gmtoff); 3558bd0e834aea317236d574f8738fe11a51fdc87968Erik invalidate(); 3559bd0e834aea317236d574f8738fe11a51fdc87968Erik } 3560bd0e834aea317236d574f8738fe11a51fdc87968Erik } 3561ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3562ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener { 3563ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3564ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onSingleTapUp(MotionEvent ev) { 3565d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doSingleTapUp(ev); 3566ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3567ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3568ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3569ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3570ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public void onLongPress(MotionEvent ev) { 3571d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doLongPress(ev); 3572ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3573ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3574ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3575ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 3576d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doScroll(e1, e2, distanceX, distanceY); 3577ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3578ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3579ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3580ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3581ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 3582d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doFling(e1, e2, velocityX, velocityY); 3583ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3584ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3585ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 3586ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 3587ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onDown(MotionEvent ev) { 3588d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doDown(ev); 3589ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 3590ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3591ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 3592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project} 3593