DayView.java revision b03348cec4c175846f074a656db5c121d5467e2d
1146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/* 2146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 4146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * you may not use this file except in compliance with the License. 6146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * You may obtain a copy of the License at 7146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 8146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 10146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * See the License for the specific language governing permissions and 14146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * limitations under the License. 15146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 16146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 17146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpackage com.android.calendar; 18146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chanimport com.android.calendar.CalendarController.EventType; 2083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chanimport com.android.calendar.CalendarController.ViewType; 2183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 2246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.Animator; 2346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.AnimatorListenerAdapter; 2446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.ObjectAnimator; 2546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.ValueAnimator; 2620b6fb580bf09dbd610a256ffd3165c03053cb70RoboErikimport android.app.AlertDialog; 279ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chanimport android.app.Service; 28146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.ContentResolver; 29146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.ContentUris; 30146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context; 3120b6fb580bf09dbd610a256ffd3165c03053cb70RoboErikimport android.content.DialogInterface; 32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.res.Resources; 33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.res.TypedArray; 34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.database.Cursor; 35146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Canvas; 36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Paint; 37e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErikimport android.graphics.Paint.Align; 38dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.graphics.Paint.Style; 39146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Rect; 40146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Typeface; 41c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawaimport android.graphics.drawable.Drawable; 42146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.net.Uri; 43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.os.Handler; 44a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees; 45a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Calendars; 46a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Events; 473e7015267340b09d142dfcd3ff8acda257711023Shachar Shemeshimport android.text.Layout.Alignment; 48e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErikimport android.text.SpannableStringBuilder; 49f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chanimport android.text.StaticLayout; 503e7015267340b09d142dfcd3ff8acda257711023Shachar Shemeshimport android.text.TextPaint; 51f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chanimport android.text.TextUtils; 52146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateFormat; 53146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateUtils; 54146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time; 55e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErikimport android.text.style.StyleSpan; 56146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.util.Log; 57146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ContextMenu; 58dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.view.ContextMenu.ContextMenuInfo; 59ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.GestureDetector; 60146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.Gravity; 61146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.KeyEvent; 62146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.LayoutInflater; 63146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.MenuItem; 64146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.MotionEvent; 65d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chanimport android.view.ScaleGestureDetector; 66146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.View; 67146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewConfiguration; 68146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewGroup; 69146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.WindowManager; 70259b8f9a21fffd3858218581e9daaf689b6b888fErikimport android.view.accessibility.AccessibilityEvent; 719ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chanimport android.view.accessibility.AccessibilityManager; 7246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.view.animation.AccelerateDecelerateInterpolator; 73ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.animation.Animation; 742c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chanimport android.view.animation.Interpolator; 75ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.animation.TranslateAnimation; 76433ba924de1ac26b923e2beb061812012749e4f3Michael Chanimport android.widget.EdgeEffect; 77146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.ImageView; 783f6328f579b05c02606572c777541b97aa04f9f3Michael Chanimport android.widget.OverScroller; 79146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.PopupWindow; 80146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.TextView; 81ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.widget.ViewSwitcher; 82146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 83146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.ArrayList; 84c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawaimport java.util.Arrays; 85146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Calendar; 86259b8f9a21fffd3858218581e9daaf689b6b888fErikimport java.util.Formatter; 87259b8f9a21fffd3858218581e9daaf689b6b888fErikimport java.util.Locale; 880d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chanimport java.util.regex.Matcher; 890d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chanimport java.util.regex.Pattern; 90146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 91146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/** 92d190418220467c02327dd9b3ae1eae238889720bMichael Chan * View for multi-day view. So far only 1 and 7 day have been tested. 93d190418220467c02327dd9b3ae1eae238889720bMichael Chan */ 94d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chanpublic class DayView extends View implements View.OnCreateContextMenuListener, 95cd405a28e6821b116dcf3c531805d0c90b6cc08cErik ScaleGestureDetector.OnScaleGestureListener, View.OnClickListener, View.OnLongClickListener 96cd405a28e6821b116dcf3c531805d0c90b6cc08cErik { 97d190418220467c02327dd9b3ae1eae238889720bMichael Chan private static String TAG = "DayView"; 98d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static boolean DEBUG = false; 999ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan private static boolean DEBUG_SCALING = false; 100259b8f9a21fffd3858218581e9daaf689b6b888fErik private static final String PERIOD_SPACE = ". "; 101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 102705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan private static float mScale = 0; // Used for supporting different screen densities 103666fc5e8ddbac15c951aad738bd818ee307eae42Erik private static final long INVALID_EVENT_ID = -1; //This is used for remembering a null event 1042fda24534978f55711526dbde747aa50d68dec40RoboErik // Duration of the allday expansion 105ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private static final long ANIMATION_DURATION = 400; 1062fda24534978f55711526dbde747aa50d68dec40RoboErik // duration of the more allday event text fade 1072fda24534978f55711526dbde747aa50d68dec40RoboErik private static final long ANIMATION_SECONDARY_DURATION = 200; 1085b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik // duration of the scroll to go to a specified time 1095b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private static final int GOTO_SCROLL_DURATION = 200; 110705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 1114484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_AGENDA = 2; 1124484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_DAY = 3; 1134484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_VIEW = 5; 1144484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_CREATE = 6; 1154484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_EDIT = 7; 1164484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_DELETE = 8; 1174484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan 11811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static int DEFAULT_CELL_HEIGHT = 64; 119d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int MAX_CELL_HEIGHT = 150; 120d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int MIN_Y_SPAN = 100; 121d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mOnFlingCalled; 1234f58287a1e02325337e39073a50bbb880094099fRoboErik private boolean mStartingScroll = false; 124ea3f117db073ae796453479d00e9c7664d4471c5RoboErik protected boolean mPaused = true; 125ea3f117db073ae796453479d00e9c7664d4471c5RoboErik private Handler mHandler; 126666fc5e8ddbac15c951aad738bd818ee307eae42Erik /** 127666fc5e8ddbac15c951aad738bd818ee307eae42Erik * ID of the last event which was displayed with the toast popup. 128666fc5e8ddbac15c951aad738bd818ee307eae42Erik * 129666fc5e8ddbac15c951aad738bd818ee307eae42Erik * This is used to prevent popping up multiple quick views for the same event, especially 130666fc5e8ddbac15c951aad738bd818ee307eae42Erik * during calendar syncs. This becomes valid when an event is selected, either by default 131666fc5e8ddbac15c951aad738bd818ee307eae42Erik * on starting calendar or by scrolling to an event. It becomes invalid when the user 132666fc5e8ddbac15c951aad738bd818ee307eae42Erik * explicitly scrolls to an empty time slot, changes views, or deletes the event. 133666fc5e8ddbac15c951aad738bd818ee307eae42Erik */ 134666fc5e8ddbac15c951aad738bd818ee307eae42Erik private long mLastPopupEventID; 135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 136ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan protected Context mContext; 137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String[] CALENDARS_PROJECTION = new String[] { 139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Calendars._ID, // 0 140ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik Calendars.CALENDAR_ACCESS_LEVEL, // 1 1416d34cec523930368976bc8d358d0a6de1da3462cMichael Chan Calendars.OWNER_ACCOUNT, // 2 142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int CALENDARS_INDEX_ACCESS_LEVEL = 1; 1446d34cec523930368976bc8d358d0a6de1da3462cMichael Chan private static final int CALENDARS_INDEX_OWNER_ACCOUNT = 2; 145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String CALENDARS_WHERE = Calendars._ID + "=%d"; 146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_NONE = 0; 148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_ABOVE = 1; 149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_BELOW = 2; 150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_LEFT = 4; 151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_RIGHT = 8; 152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 153a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_NONE = 0; 154a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_DELETE = 1; 155a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_EDIT = 2; 156a505627659f6bfba8869eac8089f7030f2d0d92cErik 157d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan private static int mHorizontalSnapBackThreshold = 128; 158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ContinueScroll mContinueScroll = new ContinueScroll(); 160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Make this visible within the package for more informative debugging 162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time mBaseDate; 163bd0e834aea317236d574f8738fe11a51fdc87968Erik private Time mCurrentTime; 164bd0e834aea317236d574f8738fe11a51fdc87968Erik //Update the current time line every five minutes if the window is left open that long 165bd0e834aea317236d574f8738fe11a51fdc87968Erik private static final int UPDATE_CURRENT_TIME_DELAY = 300000; 166bd0e834aea317236d574f8738fe11a51fdc87968Erik private UpdateCurrentTime mUpdateCurrentTime = new UpdateCurrentTime(); 167bd0e834aea317236d574f8738fe11a51fdc87968Erik private int mTodayJulianDay; 168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Typeface mBold = Typeface.DEFAULT_BOLD; 170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstJulianDay; 171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mLastJulianDay; 172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMonthLength; 174487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstVisibleDate; 175487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstVisibleDayOfWeek; 176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int[] mEarliestStartHour; // indexed by the week day offset 177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean[] mHasAllDayEvent; // indexed by the week day offset 178259b8f9a21fffd3858218581e9daaf689b6b888fErik private String mEventCountTemplate; 17920b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik private CharSequence[] mLongPressItems; 18020b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik private String mLongPressTitle; 181259b8f9a21fffd3858218581e9daaf689b6b888fErik 182259b8f9a21fffd3858218581e9daaf689b6b888fErik protected static StringBuilder mStringBuilder = new StringBuilder(50); 183259b8f9a21fffd3858218581e9daaf689b6b888fErik // TODO recreate formatter when locale changes 184259b8f9a21fffd3858218581e9daaf689b6b888fErik protected static Formatter mFormatter = new Formatter(mStringBuilder, Locale.getDefault()); 185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 186731f1cb808b7586b93615b408ab2636081fab0dcErik private Runnable mTZUpdater = new Runnable() { 187731f1cb808b7586b93615b408ab2636081fab0dcErik @Override 188731f1cb808b7586b93615b408ab2636081fab0dcErik public void run() { 189731f1cb808b7586b93615b408ab2636081fab0dcErik String tz = Utils.getTimeZone(mContext, this); 190731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate.timezone = tz; 191731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate.normalize(true); 192731f1cb808b7586b93615b408ab2636081fab0dcErik mCurrentTime.switchTimezone(tz); 193731f1cb808b7586b93615b408ab2636081fab0dcErik invalidate(); 194731f1cb808b7586b93615b408ab2636081fab0dcErik } 195731f1cb808b7586b93615b408ab2636081fab0dcErik }; 196731f1cb808b7586b93615b408ab2636081fab0dcErik 1975b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private TodayAnimatorListener mTodayAnimatorListener = new TodayAnimatorListener(); 1985b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 1995b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik class TodayAnimatorListener extends AnimatorListenerAdapter { 2005b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private volatile Animator mAnimator = null; 2015b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private volatile boolean mFadingIn = false; 2025b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 2035b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik @Override 2045b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void onAnimationEnd(Animator animation) { 2055b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik synchronized (this) { 2065b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mAnimator != animation) { 2075b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik animation.removeAllListeners(); 2085b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik animation.cancel(); 2095b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik return; 2105b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2115b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mFadingIn) { 2125b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mTodayAnimator != null) { 2135b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.removeAllListeners(); 2145b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.cancel(); 2155b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2165b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator = ObjectAnimator 2175b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik .ofInt(DayView.this, "animateTodayAlpha", 255, 0); 2185b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimator = mTodayAnimator; 2195b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mFadingIn = false; 2205b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.addListener(this); 2215b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.setDuration(600); 2225b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.start(); 2235b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } else { 2245b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateToday = false; 2255b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateTodayAlpha = 0; 2265b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimator.removeAllListeners(); 2275b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimator = null; 2285b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator = null; 2295b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik invalidate(); 2305b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2315b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2325b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2335b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 2345b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void setAnimator(Animator animation) { 2355b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimator = animation; 2365b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2375b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 2385b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void setFadingIn(boolean fadingIn) { 2395b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mFadingIn = fadingIn; 2405b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2415b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 2425b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2435b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 24446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() { 24546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 24646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void onAnimationStart(Animator animation) { 24746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = true; 24846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 24946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 25046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 25146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void onAnimationCancel(Animator animation) { 25246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = false; 25346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 25446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 25546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 25646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void onAnimationEnd(Animator animation) { 25746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = false; 25846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan resetSelectedHour(); 25946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan invalidate(); 26046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 26146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan }; 26246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * This variable helps to avoid unnecessarily reloading events by keeping 265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * track of the start millis parameter used for the most recent loading 266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * of events. If the next reload matches this, then the events are not 267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * reloaded. To force a reload, set this to zero (this is set to zero 268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * in the method clearCachedEvents()). 269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private long mLastReloadMillis; 271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ArrayList<Event> mEvents = new ArrayList<Event>(); 27308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private ArrayList<Event> mAllDayEvents = new ArrayList<Event>(); 27408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout[] mLayouts = null; 27508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout[] mAllDayLayouts = null; 276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionDay; // Julian day 277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionHour; 278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2792fda24534978f55711526dbde747aa50d68dec40RoboErik boolean mSelectionAllday; 280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2819ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan private int mLastSelectionDay; 2829ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan private int mLastSelectionHour; 2839ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan private Event mLastSelectedEvent; 2849ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 2853eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan /** Width of a day or non-conflicting event */ 286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mCellWidth; 287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pre-allocate these objects and re-use them 289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mRect = new Rect(); 290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mDestRect = new Rect(); 291259b8f9a21fffd3858218581e9daaf689b6b888fErik private Rect mSelectionRect = new Rect(); 2922fda24534978f55711526dbde747aa50d68dec40RoboErik // This encloses the more allDay events icon 2932fda24534978f55711526dbde747aa50d68dec40RoboErik private Rect mExpandAllDayRect = new Rect(); 294e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik // TODO Clean up paint usage 295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mPaint = new Paint(); 296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mEventTextPaint = new Paint(); 297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Paint mSelectionPaint = new Paint(); 29802041687c35441e8a21cb763f1fc3a26525292efDavid Brown private float[] mLines; 299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 300487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstDayOfWeek; // First day of the week 301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private PopupWindow mPopup; 303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private View mPopupView; 304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The number of milliseconds to show the popup window 306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int POPUP_DISMISS_DELAY = 3000; 307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private DismissPopup mDismissPopup = new DismissPopup(); 308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mRemeasure = true; 310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private final EventLoader mEventLoader; 312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected final EventGeometry mEventGeometry; 313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 314e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static float GRID_LINE_LEFT_MARGIN = 0; 315000ba1109e2f4e527e9227fe341598ceeb3fbca6Michael Chan private static final float GRID_LINE_INNER_WIDTH = 1; 3163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int DAY_GAP = 1; 318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int HOUR_GAP = 1; 3192fda24534978f55711526dbde747aa50d68dec40RoboErik // This is the standard height of an allday event with no restrictions 3209c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private static int SINGLE_ALLDAY_HEIGHT = 34; 3212fda24534978f55711526dbde747aa50d68dec40RoboErik /** 3222fda24534978f55711526dbde747aa50d68dec40RoboErik * This is the minimum desired height of a allday event. 3232fda24534978f55711526dbde747aa50d68dec40RoboErik * When unexpanded, allday events will use this height. 3242fda24534978f55711526dbde747aa50d68dec40RoboErik * When expanded allDay events will attempt to grow to fit all 3252fda24534978f55711526dbde747aa50d68dec40RoboErik * events at this height. 3262fda24534978f55711526dbde747aa50d68dec40RoboErik */ 3272fda24534978f55711526dbde747aa50d68dec40RoboErik private static float MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT = 28.0F; // in pixels 3282fda24534978f55711526dbde747aa50d68dec40RoboErik /** 3292fda24534978f55711526dbde747aa50d68dec40RoboErik * This is how big the unexpanded allday height is allowed to be. 3302fda24534978f55711526dbde747aa50d68dec40RoboErik * It will get adjusted based on screen size 3312fda24534978f55711526dbde747aa50d68dec40RoboErik */ 3322fda24534978f55711526dbde747aa50d68dec40RoboErik private static int MAX_UNEXPANDED_ALLDAY_HEIGHT = 3332fda24534978f55711526dbde747aa50d68dec40RoboErik (int) (MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT * 4); 3342fda24534978f55711526dbde747aa50d68dec40RoboErik /** 3352fda24534978f55711526dbde747aa50d68dec40RoboErik * This is the minimum size reserved for displaying regular events. 3362fda24534978f55711526dbde747aa50d68dec40RoboErik * The expanded allDay region can't expand into this. 3372fda24534978f55711526dbde747aa50d68dec40RoboErik */ 3382fda24534978f55711526dbde747aa50d68dec40RoboErik private static int MIN_HOURS_HEIGHT = 180; 33925996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private static int ALLDAY_TOP_MARGIN = 1; 3402fda24534978f55711526dbde747aa50d68dec40RoboErik // The largest a single allDay event will become. 341f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan private static int MAX_HEIGHT_OF_ONE_ALLDAY_EVENT = 34; 342e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3438f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int HOURS_TOP_MARGIN = 2; 344e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int HOURS_LEFT_MARGIN = 2; 3458f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int HOURS_RIGHT_MARGIN = 4; 3468f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int HOURS_MARGIN = HOURS_LEFT_MARGIN + HOURS_RIGHT_MARGIN; 34795f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan private static int NEW_EVENT_MARGIN = 4; 348462196d197de326006aaf15f8bb7a8d83b8e2a60Peter Ng private static int NEW_EVENT_WIDTH = 2; 34995f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan private static int NEW_EVENT_MAX_LENGTH = 16; 350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 351bd0e834aea317236d574f8738fe11a51fdc87968Erik private static int CURRENT_TIME_LINE_HEIGHT = 2; 352bd0e834aea317236d574f8738fe11a51fdc87968Erik private static int CURRENT_TIME_LINE_BORDER_WIDTH = 1; 353763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int CURRENT_TIME_LINE_SIDE_BUFFER = 4; 354763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int CURRENT_TIME_LINE_TOP_OFFSET = 2; 355bd0e834aea317236d574f8738fe11a51fdc87968Erik 356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MINUTES_PER_HOUR = 60; 357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MINUTES_PER_DAY = MINUTES_PER_HOUR * 24; 358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_MINUTE = 60 * 1000; 359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_HOUR = (3600 * 1000); 360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_DAY = MILLIS_PER_HOUR * 24; 361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3622fda24534978f55711526dbde747aa50d68dec40RoboErik // More events text will transition between invisible and this alpha 3632fda24534978f55711526dbde747aa50d68dec40RoboErik private static final int MORE_EVENTS_MAX_ALPHA = 0x4C; 364e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_ONE_DAY_LEFT_MARGIN = 0; 365e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_ONE_DAY_RIGHT_MARGIN = 5; 366e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_ONE_DAY_BOTTOM_MARGIN = 6; 367e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_LEFT_MARGIN = 5; 368e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_RIGHT_MARGIN = 4; 369e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_BOTTOM_MARGIN = 3; 3703eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_FONT_SIZE = 14; 3718f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static float DATE_HEADER_FONT_SIZE = 32; 3723eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float NORMAL_FONT_SIZE = 12; 3733eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float EVENT_TEXT_FONT_SIZE = 12; 374e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static float HOURS_TEXT_SIZE = 12; 375e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static float AMPM_TEXT_SIZE = 9; 3768f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int MIN_HOURS_WIDTH = 96; 377763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int MIN_CELL_WIDTH_FOR_TEXT = 20; 378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int MAX_EVENT_TEXT_LEN = 500; 3792fda24534978f55711526dbde747aa50d68dec40RoboErik // smallest height to draw an event with 38025996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private static float MIN_EVENT_HEIGHT = 24.0F; // in pixels 3811ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int CALENDAR_COLOR_SQUARE_SIZE = 10; 38225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private static int EVENT_RECT_TOP_MARGIN = 1; 383763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int EVENT_RECT_BOTTOM_MARGIN = 0; 384763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int EVENT_RECT_LEFT_MARGIN = 1; 385763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int EVENT_RECT_RIGHT_MARGIN = 0; 38625996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private static int EVENT_RECT_STROKE_WIDTH = 2; 3871ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_TEXT_TOP_MARGIN = 2; 38825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private static int EVENT_TEXT_BOTTOM_MARGIN = 2; 38995d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng private static int EVENT_TEXT_LEFT_MARGIN = 6; 39095d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng private static int EVENT_TEXT_RIGHT_MARGIN = 6; 391e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int ALL_DAY_EVENT_RECT_BOTTOM_MARGIN = 1; 3921ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_TOP_MARGIN = EVENT_TEXT_TOP_MARGIN; 3931ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN = EVENT_TEXT_BOTTOM_MARGIN; 3941ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_LEFT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 3951ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_RIGHT_MARGIN = EVENT_TEXT_RIGHT_MARGIN; 3962fda24534978f55711526dbde747aa50d68dec40RoboErik // margins and sizing for the expand allday icon 397cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik private static int EXPAND_ALL_DAY_BOTTOM_MARGIN = 10; 3982fda24534978f55711526dbde747aa50d68dec40RoboErik // sizing for "box +n" in allDay events 3992fda24534978f55711526dbde747aa50d68dec40RoboErik private static int EVENT_SQUARE_WIDTH = 10; 4002fda24534978f55711526dbde747aa50d68dec40RoboErik private static int EVENT_LINE_PADDING = 4; 401ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson private static int NEW_EVENT_HINT_FONT_SIZE = 12; 402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mPressedColor; 404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mEventTextColor; 4052fda24534978f55711526dbde747aa50d68dec40RoboErik private static int mMoreEventsTextColor; 406f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan 40764b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok private static int mWeek_saturdayColor; 40864b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok private static int mWeek_sundayColor; 409d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarDateBannerTextColor; 410d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarAmPmLabel; 411ba902466b19b11d587468e354edc58e542707747Michael Chan private static int mCalendarGridAreaSelected; 4123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int mCalendarGridLineInnerHorizontalColor; 4133eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int mCalendarGridLineInnerVerticalColor; 41421bd42039c92232647f54461cd20708224cc7eb6Michael Chan private static int mFutureBgColor; 415cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan private static int mFutureBgColorRes; 416e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int mBgColor; 417ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson private static int mNewEventHintColor; 4188f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int mCalendarHourLabelColor; 4192fda24534978f55711526dbde747aa50d68dec40RoboErik private static int mMoreAlldayEventsTextAlpha = MORE_EVENTS_MAX_ALPHA; 420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 42195d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan private float mAnimationDistance = 0; 422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewStartX; 423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewStartY; 424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMaxViewStartY; 425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewHeight; 426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewWidth; 42746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan private int mGridAreaHeight = -1; 428d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int mCellHeight = 0; // shared among all DayViews 429d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int mMinCellHeight = 32; 430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mScrollStartY; 431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mPreviousDirection; 432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 433d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** 434d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * Vertical distance or span between the two touch points at the start of a 435d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * scaling gesture 436d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan */ 437d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private float mStartingSpanY = 0; 438d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** Height of 1 hour in pixels at the start of a scaling gesture */ 439d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private int mCellHeightBeforeScaleGesture; 440d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** The hour at the center two touch points */ 441d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private float mGestureCenterHour = 0; 442d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** 443d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * Flag to decide whether to handle the up event. Cases where up events 444d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * should be ignored are 1) right after a scale gesture and 2) finger was 445d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * down before app launch 446d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan */ 447d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private boolean mHandleActionUp = true; 448d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mHoursTextHeight; 4502fda24534978f55711526dbde747aa50d68dec40RoboErik /** 4512fda24534978f55711526dbde747aa50d68dec40RoboErik * The height of the area used for allday events 4522fda24534978f55711526dbde747aa50d68dec40RoboErik */ 4532fda24534978f55711526dbde747aa50d68dec40RoboErik private int mAlldayHeight; 4542fda24534978f55711526dbde747aa50d68dec40RoboErik /** 4552fda24534978f55711526dbde747aa50d68dec40RoboErik * The height of the allday event area used during animation 4562fda24534978f55711526dbde747aa50d68dec40RoboErik */ 4572fda24534978f55711526dbde747aa50d68dec40RoboErik private int mAnimateDayHeight = 0; 4582fda24534978f55711526dbde747aa50d68dec40RoboErik /** 4592fda24534978f55711526dbde747aa50d68dec40RoboErik * The height of an individual allday event during animation 4602fda24534978f55711526dbde747aa50d68dec40RoboErik */ 4612fda24534978f55711526dbde747aa50d68dec40RoboErik private int mAnimateDayEventHeight = (int) MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT; 4622fda24534978f55711526dbde747aa50d68dec40RoboErik /** 463cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik * Whether to use the expand or collapse icon. 4642fda24534978f55711526dbde747aa50d68dec40RoboErik */ 46597326ee1ea9b1bb17e0e2bcfe344352d4bb03001RoboErik private static boolean mUseExpandIcon = true; 4662fda24534978f55711526dbde747aa50d68dec40RoboErik /** 4672fda24534978f55711526dbde747aa50d68dec40RoboErik * The height of the day names/numbers 4682fda24534978f55711526dbde747aa50d68dec40RoboErik */ 4693eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int DAY_HEADER_HEIGHT = 45; 470f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan /** 471e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * The height of the day names/numbers for multi-day views 472e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik */ 473e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int MULTI_DAY_HEADER_HEIGHT = DAY_HEADER_HEIGHT; 474e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik /** 475e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * The height of the day names/numbers when viewing a single day 476e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik */ 477e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int ONE_DAY_HEADER_HEIGHT = DAY_HEADER_HEIGHT; 478e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik /** 479f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan * Max of all day events in a given day in this view. 480f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan */ 4812fda24534978f55711526dbde747aa50d68dec40RoboErik private int mMaxAlldayEvents; 4822fda24534978f55711526dbde747aa50d68dec40RoboErik /** 4832fda24534978f55711526dbde747aa50d68dec40RoboErik * A count of the number of allday events that were not drawn for each day 4842fda24534978f55711526dbde747aa50d68dec40RoboErik */ 4852fda24534978f55711526dbde747aa50d68dec40RoboErik private int[] mSkippedAlldayEvents; 4862fda24534978f55711526dbde747aa50d68dec40RoboErik /** 4872fda24534978f55711526dbde747aa50d68dec40RoboErik * The number of allDay events at which point we start hiding allDay events. 4882fda24534978f55711526dbde747aa50d68dec40RoboErik */ 4892fda24534978f55711526dbde747aa50d68dec40RoboErik private int mMaxUnexpandedAlldayEventCount = 4; 4902fda24534978f55711526dbde747aa50d68dec40RoboErik /** 4912fda24534978f55711526dbde747aa50d68dec40RoboErik * Whether or not to expand the allDay area to fill the screen 4922fda24534978f55711526dbde747aa50d68dec40RoboErik */ 4932fda24534978f55711526dbde747aa50d68dec40RoboErik private static boolean mShowAllAllDayEvents = false; 494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected int mNumDays = 7; 496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mNumHours = 10; 4973eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 4983eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan /** Width of the time line (list of hours) to the left. */ 499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mHoursWidth; 500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mDateStrWidth; 50146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** Top of the scrollable region i.e. below date labels and all day events */ 502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstCell; 50346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** First fully visibile hour */ 504146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstHour = -1; 50546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** Distance between the mFirstCell and the top of first fully visible hour. */ 506146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstHourOffset; 507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mHourStrs; 508146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mDayStrs; 509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mDayStrs2Letter; 510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mIs24HourFormat; 511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 512146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ArrayList<Event> mSelectedEvents = new ArrayList<Event>(); 513146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mComputeSelectedEvents; 5148307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik private boolean mUpdateToast; 515146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Event mSelectedEvent; 516146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Event mPrevSelectedEvent; 517146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect mPrevBox = new Rect(); 518146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected final Resources mResources; 5193eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan protected final Drawable mCurrentTimeLine; 5205b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik protected final Drawable mCurrentTimeAnimateLine; 5213eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan protected final Drawable mTodayHeaderDrawable; 5222fda24534978f55711526dbde747aa50d68dec40RoboErik protected final Drawable mExpandAlldayDrawable; 523cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik protected final Drawable mCollapseAlldayDrawable; 524f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan protected Drawable mAcceptedOrTentativeEventBoxDrawable; 525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String mAmString; 526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String mPmString; 527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private DeleteEventHelper mDeleteEventHelper; 5286d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private static int sCounter = 0; 529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ContextMenuHandler mContextMenuHandler = new ContextMenuHandler(); 531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 532d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan ScaleGestureDetector mScaleGestureDetector; 533d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The initial state of the touch mode when we enter this view. 536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_INITIAL_STATE = 0; 538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates we just received the touch event and we are waiting to see if 541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * it is a tap or a scroll gesture. 542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_DOWN = 1; 544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 546146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates the touch gesture is a vertical scroll 547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_VSCROLL = 0x20; 549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates the touch gesture is a horizontal scroll 552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_HSCROLL = 0x40; 554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mTouchMode = TOUCH_MODE_INITIAL_STATE; 556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The selection modes are HIDDEN, PRESSED, SELECTED, and LONGPRESS. 559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_HIDDEN = 0; 561ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan private static final int SELECTION_PRESSED = 1; // D-pad down but not up yet 562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_SELECTED = 2; 563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_LONGPRESS = 3; 564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionMode = SELECTION_HIDDEN; 566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mScrolling = false; 568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 5694f58287a1e02325337e39073a50bbb880094099fRoboErik private float mInitialScrollX; 5704f58287a1e02325337e39073a50bbb880094099fRoboErik private float mInitialScrollY; 5712fda24534978f55711526dbde747aa50d68dec40RoboErik 5725b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private boolean mAnimateToday = false; 5735b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private int mAnimateTodayAlpha = 0; 5745b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 5752fda24534978f55711526dbde747aa50d68dec40RoboErik // Animates the height of the allday region 5762fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator mAlldayAnimator; 5772fda24534978f55711526dbde747aa50d68dec40RoboErik // Animates the height of events in the allday region 5782fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator mAlldayEventAnimator; 5792fda24534978f55711526dbde747aa50d68dec40RoboErik // Animates the transparency of the more events text 5802fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator mMoreAlldayEventsAnimator; 5815b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik // Animates the current time marker when Today is pressed 5825b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik ObjectAnimator mTodayAnimator; 5832fda24534978f55711526dbde747aa50d68dec40RoboErik // whether or not an event is stopping because it was cancelled 5842fda24534978f55711526dbde747aa50d68dec40RoboErik private boolean mCancellingAnimations = false; 5852fda24534978f55711526dbde747aa50d68dec40RoboErik // tracks whether a touch originated in the allday area 5862fda24534978f55711526dbde747aa50d68dec40RoboErik private boolean mTouchStartedInAlldayArea = false; 5872fda24534978f55711526dbde747aa50d68dec40RoboErik 588ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private CalendarController mController; 589ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private ViewSwitcher mViewSwitcher; 590ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan private GestureDetector mGestureDetector; 5913f6328f579b05c02606572c777541b97aa04f9f3Michael Chan private OverScroller mScroller; 592433ba924de1ac26b923e2beb061812012749e4f3Michael Chan private EdgeEffect mEdgeEffectTop; 593433ba924de1ac26b923e2beb061812012749e4f3Michael Chan private EdgeEffect mEdgeEffectBottom; 594433ba924de1ac26b923e2beb061812012749e4f3Michael Chan private boolean mCallEdgeEffectOnAbsorb; 595433ba924de1ac26b923e2beb061812012749e4f3Michael Chan private final int OVERFLING_DISTANCE; 596433ba924de1ac26b923e2beb061812012749e4f3Michael Chan private float mLastVelocity; 597433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 5982c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan private ScrollInterpolator mHScrollInterpolator; 599aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan private AccessibilityManager mAccessibilityMgr = null; 600aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan private boolean mIsAccessibilityEnabled = false; 6019ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan private boolean mTouchExplorationEnabled = false; 6029ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan private String mCreateNewEventString; 603ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson private String mNewEventHintString; 604705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 605d190418220467c02327dd9b3ae1eae238889720bMichael Chan public DayView(Context context, CalendarController controller, 60675d9b567e1fd3b9c6945cd0afe28781f5a19c6c8Michael Chan ViewSwitcher viewSwitcher, EventLoader eventLoader, int numDays) { 607ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan super(context); 608aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mContext = context; 609aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan initAccessibilityVariables(); 610aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan 6112fda24534978f55711526dbde747aa50d68dec40RoboErik mResources = context.getResources(); 6129ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan mCreateNewEventString = mResources.getString(R.string.event_create); 613ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson mNewEventHintString = mResources.getString(R.string.day_view_new_event_hint); 61400671d5b9254772d223587b3b831d5816476f681Michael Chan mNumDays = numDays; 61509b1b2e1e7eb9bc291d4e70c993471d3c9ffa799Michael Chan 616e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik DATE_HEADER_FONT_SIZE = (int) mResources.getDimension(R.dimen.date_header_text_size); 617e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik DAY_HEADER_FONT_SIZE = (int) mResources.getDimension(R.dimen.day_label_text_size); 618e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik ONE_DAY_HEADER_HEIGHT = (int) mResources.getDimension(R.dimen.one_day_header_height); 619e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik DAY_HEADER_BOTTOM_MARGIN = (int) mResources.getDimension(R.dimen.day_header_bottom_margin); 620e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik EXPAND_ALL_DAY_BOTTOM_MARGIN = (int) mResources.getDimension(R.dimen.all_day_bottom_margin); 621e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik HOURS_TEXT_SIZE = (int) mResources.getDimension(R.dimen.hours_text_size); 622e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik AMPM_TEXT_SIZE = (int) mResources.getDimension(R.dimen.ampm_text_size); 623e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik MIN_HOURS_WIDTH = (int) mResources.getDimension(R.dimen.min_hours_width); 624e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik HOURS_LEFT_MARGIN = (int) mResources.getDimension(R.dimen.hours_left_margin); 625e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik HOURS_RIGHT_MARGIN = (int) mResources.getDimension(R.dimen.hours_right_margin); 626e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik MULTI_DAY_HEADER_HEIGHT = (int) mResources.getDimension(R.dimen.day_header_height); 62700671d5b9254772d223587b3b831d5816476f681Michael Chan int eventTextSizeId; 62800671d5b9254772d223587b3b831d5816476f681Michael Chan if (mNumDays == 1) { 62900671d5b9254772d223587b3b831d5816476f681Michael Chan eventTextSizeId = R.dimen.day_view_event_text_size; 63000671d5b9254772d223587b3b831d5816476f681Michael Chan } else { 63100671d5b9254772d223587b3b831d5816476f681Michael Chan eventTextSizeId = R.dimen.week_view_event_text_size; 63200671d5b9254772d223587b3b831d5816476f681Michael Chan } 63300671d5b9254772d223587b3b831d5816476f681Michael Chan EVENT_TEXT_FONT_SIZE = (int) mResources.getDimension(eventTextSizeId); 634ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson NEW_EVENT_HINT_FONT_SIZE = (int) mResources.getDimension(R.dimen.new_event_hint_text_size); 6355ca51369b44901fbab6da0ac67b3001c19f2ae29RoboErik MIN_EVENT_HEIGHT = mResources.getDimension(R.dimen.event_min_height); 636714c299ea5c05858e273d98efbacf20fedd328f1RoboErik MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT = MIN_EVENT_HEIGHT; 6375ca51369b44901fbab6da0ac67b3001c19f2ae29RoboErik EVENT_TEXT_TOP_MARGIN = (int) mResources.getDimension(R.dimen.event_text_vertical_margin); 6385ca51369b44901fbab6da0ac67b3001c19f2ae29RoboErik EVENT_TEXT_BOTTOM_MARGIN = EVENT_TEXT_TOP_MARGIN; 6395ca51369b44901fbab6da0ac67b3001c19f2ae29RoboErik EVENT_ALL_DAY_TEXT_TOP_MARGIN = EVENT_TEXT_TOP_MARGIN; 6405ca51369b44901fbab6da0ac67b3001c19f2ae29RoboErik EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN = EVENT_TEXT_TOP_MARGIN; 64109b1b2e1e7eb9bc291d4e70c993471d3c9ffa799Michael Chan 64295d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng EVENT_TEXT_LEFT_MARGIN = (int) mResources 64395d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng .getDimension(R.dimen.event_text_horizontal_margin); 64495d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng EVENT_TEXT_RIGHT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 64595d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng EVENT_ALL_DAY_TEXT_LEFT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 64695d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng EVENT_ALL_DAY_TEXT_RIGHT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 64795d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng 648705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan if (mScale == 0) { 649e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 6502fda24534978f55711526dbde747aa50d68dec40RoboErik mScale = mResources.getDisplayMetrics().density; 651705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan if (mScale != 1) { 652705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan SINGLE_ALLDAY_HEIGHT *= mScale; 653705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan ALLDAY_TOP_MARGIN *= mScale; 654f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan MAX_HEIGHT_OF_ONE_ALLDAY_EVENT *= mScale; 655705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 656705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan NORMAL_FONT_SIZE *= mScale; 6578f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan GRID_LINE_LEFT_MARGIN *= mScale; 6588f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan HOURS_TOP_MARGIN *= mScale; 659705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan MIN_CELL_WIDTH_FOR_TEXT *= mScale; 6602fda24534978f55711526dbde747aa50d68dec40RoboErik MAX_UNEXPANDED_ALLDAY_HEIGHT *= mScale; 6612fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayEventHeight = (int) MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT; 662705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 663bd0e834aea317236d574f8738fe11a51fdc87968Erik CURRENT_TIME_LINE_HEIGHT *= mScale; 664bd0e834aea317236d574f8738fe11a51fdc87968Erik CURRENT_TIME_LINE_BORDER_WIDTH *= mScale; 665763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik CURRENT_TIME_LINE_SIDE_BUFFER *= mScale; 666763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik CURRENT_TIME_LINE_TOP_OFFSET *= mScale; 667bd0e834aea317236d574f8738fe11a51fdc87968Erik 668d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan MIN_Y_SPAN *= mScale; 669d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan MAX_CELL_HEIGHT *= mScale; 670697157470a6f0d8e7b806af9b4fb7fbe0bccae87Erik DEFAULT_CELL_HEIGHT *= mScale; 6713eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_HEIGHT *= mScale; 6723eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_LEFT_MARGIN *= mScale; 6733eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_RIGHT_MARGIN *= mScale; 6743eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_LEFT_MARGIN *= mScale; 6753eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_RIGHT_MARGIN *= mScale; 6763eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_BOTTOM_MARGIN *= mScale; 6773eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan CALENDAR_COLOR_SQUARE_SIZE *= mScale; 67811ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_TOP_MARGIN *= mScale; 67911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_BOTTOM_MARGIN *= mScale; 68025996100d6ea61888ebe54d7708a9a371bb12a55RoboErik ALL_DAY_EVENT_RECT_BOTTOM_MARGIN *= mScale; 68111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_LEFT_MARGIN *= mScale; 68211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_RIGHT_MARGIN *= mScale; 68325996100d6ea61888ebe54d7708a9a371bb12a55RoboErik EVENT_RECT_STROKE_WIDTH *= mScale; 6842fda24534978f55711526dbde747aa50d68dec40RoboErik EVENT_SQUARE_WIDTH *= mScale; 6852fda24534978f55711526dbde747aa50d68dec40RoboErik EVENT_LINE_PADDING *= mScale; 68695f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan NEW_EVENT_MARGIN *= mScale; 68795f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan NEW_EVENT_WIDTH *= mScale; 68895f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan NEW_EVENT_MAX_LENGTH *= mScale; 689705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan } 690705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan } 691e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik HOURS_MARGIN = HOURS_LEFT_MARGIN + HOURS_RIGHT_MARGIN; 69200671d5b9254772d223587b3b831d5816476f681Michael Chan DAY_HEADER_HEIGHT = mNumDays == 1 ? ONE_DAY_HEADER_HEIGHT : MULTI_DAY_HEADER_HEIGHT; 693705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 6949175d29276c78a2a294ce2fce112432171ef7c7cRoboErik mCurrentTimeLine = mResources.getDrawable(R.drawable.timeline_indicator_holo_light); 6955b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mCurrentTimeAnimateLine = mResources 6965b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik .getDrawable(R.drawable.timeline_indicator_activated_holo_light); 6973eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable = mResources.getDrawable(R.drawable.today_blue_week_holo_light); 69899704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan mExpandAlldayDrawable = mResources.getDrawable(R.drawable.ic_expand_holo_light); 69999704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan mCollapseAlldayDrawable = mResources.getDrawable(R.drawable.ic_collapse_holo_light); 700ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson mNewEventHintColor = mResources.getColor(R.color.new_event_hint_text_color); 701f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan mAcceptedOrTentativeEventBoxDrawable = mResources 702f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan .getDrawable(R.drawable.panel_month_event_holo_light); 70325996100d6ea61888ebe54d7708a9a371bb12a55RoboErik 704ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mEventLoader = eventLoader; 705146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry = new EventGeometry(); 706146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setMinEventHeight(MIN_EVENT_HEIGHT); 707146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setHourGap(HOUR_GAP); 708e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mEventGeometry.setCellMargin(DAY_GAP); 70920b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik mLongPressItems = new CharSequence[] { 71020b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik mResources.getString(R.string.new_event_dialog_option) 71120b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik }; 71220b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik mLongPressTitle = mResources.getString(R.string.new_event_dialog_label); 713ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mDeleteEventHelper = new DeleteEventHelper(context, null, false /* don't exit when done */); 714666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 715ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mController = controller; 716ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher = viewSwitcher; 717ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector = new GestureDetector(context, new CalendarGestureListener()); 718d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mScaleGestureDetector = new ScaleGestureDetector(getContext(), this); 719d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight == 0) { 720d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = Utils.getSharedPreference(mContext, 721d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan GeneralPreferences.KEY_DEFAULT_CELL_HEIGHT, DEFAULT_CELL_HEIGHT); 722d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 7233f6328f579b05c02606572c777541b97aa04f9f3Michael Chan mScroller = new OverScroller(context); 7242c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan mHScrollInterpolator = new ScrollInterpolator(); 725433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop = new EdgeEffect(context); 726433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom = new EdgeEffect(context); 727433ba924de1ac26b923e2beb061812012749e4f3Michael Chan OVERFLING_DISTANCE = ViewConfiguration.get(context).getScaledOverflingDistance(); 728433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 729ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan init(context); 730146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 731146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 732ea3f117db073ae796453479d00e9c7664d4471c5RoboErik @Override 733ea3f117db073ae796453479d00e9c7664d4471c5RoboErik protected void onAttachedToWindow() { 734ea3f117db073ae796453479d00e9c7664d4471c5RoboErik if (mHandler == null) { 735ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler = getHandler(); 736ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.post(mUpdateCurrentTime); 737ea3f117db073ae796453479d00e9c7664d4471c5RoboErik } 738ea3f117db073ae796453479d00e9c7664d4471c5RoboErik } 739ea3f117db073ae796453479d00e9c7664d4471c5RoboErik 740146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void init(Context context) { 741146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setFocusable(true); 742146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 743146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allow focus in touch mode so that we can do keyboard shortcuts 744146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // even after we've entered touch mode. 745146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setFocusableInTouchMode(true); 746146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setClickable(true); 747146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setOnCreateContextMenuListener(this); 748146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 749487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstDayOfWeek = Utils.getFirstDayOfWeek(context); 750146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 751731f1cb808b7586b93615b408ab2636081fab0dcErik mCurrentTime = new Time(Utils.getTimeZone(context, mTZUpdater)); 752bd0e834aea317236d574f8738fe11a51fdc87968Erik long currentTime = System.currentTimeMillis(); 753bd0e834aea317236d574f8738fe11a51fdc87968Erik mCurrentTime.set(currentTime); 754bd0e834aea317236d574f8738fe11a51fdc87968Erik mTodayJulianDay = Time.getJulianDay(currentTime, mCurrentTime.gmtoff); 755bd0e834aea317236d574f8738fe11a51fdc87968Erik 75664b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok mWeek_saturdayColor = mResources.getColor(R.color.week_saturday); 75764b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok mWeek_sundayColor = mResources.getColor(R.color.week_sunday); 758d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarDateBannerTextColor = mResources.getColor(R.color.calendar_date_banner_text_color); 759cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan mFutureBgColorRes = mResources.getColor(R.color.calendar_future_bg_color); 760e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mBgColor = mResources.getColor(R.color.calendar_hour_background); 761d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarAmPmLabel = mResources.getColor(R.color.calendar_ampm_label); 762ba902466b19b11d587468e354edc58e542707747Michael Chan mCalendarGridAreaSelected = mResources.getColor(R.color.calendar_grid_area_selected); 763e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mCalendarGridLineInnerHorizontalColor = mResources 764e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik .getColor(R.color.calendar_grid_line_inner_horizontal_color); 765e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mCalendarGridLineInnerVerticalColor = mResources 766e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik .getColor(R.color.calendar_grid_line_inner_vertical_color); 7678f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mCalendarHourLabelColor = mResources.getColor(R.color.calendar_hour_label); 768146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPressedColor = mResources.getColor(R.color.pressed); 769146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextColor = mResources.getColor(R.color.calendar_event_text_color); 770e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mMoreEventsTextColor = mResources.getColor(R.color.month_event_other_color); 77111638ad4fb56b978770aebe75deac7a0e6ac60d2Erik 772146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setTextSize(EVENT_TEXT_FONT_SIZE); 773146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setTextAlign(Paint.Align.LEFT); 774146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setAntiAlias(true); 775146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 776146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int gridLineColor = mResources.getColor(R.color.calendar_grid_line_highlight_color); 777146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mSelectionPaint; 778146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setColor(gridLineColor); 7793937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setStyle(Style.FILL); 780146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 781146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 782146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p = mPaint; 783146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 784146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 785146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allocate space for 2 weeks worth of weekday names so that we can 786146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // easily start the week display at any week day. 787146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs = new String[14]; 788146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 789146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also create an array of 2-letter abbreviations. 790146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter = new String[14]; 791146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 792146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) { 793146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int index = i - Calendar.SUNDAY; 794146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // e.g. Tue for Tuesday 795e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mDayStrs[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_MEDIUM) 796e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik .toUpperCase(); 797146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs[index + 7] = mDayStrs[index]; 798146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // e.g. Tu for Tuesday 799e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mDayStrs2Letter[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_SHORT) 800e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik .toUpperCase(); 80152b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer 80252b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer // If we don't have 2-letter day strings, fall back to 1-letter. 80352b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer if (mDayStrs2Letter[index].equals(mDayStrs[index])) { 80452b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer mDayStrs2Letter[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_SHORTEST); 80552b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer } 80652b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer 807146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter[index + 7] = mDayStrs2Letter[index]; 808146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 809146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 810146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out how much space we need for the 3-letter abbrev names 811146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // in the worst case. 8123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 813146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 814146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] dateStrs = {" 28", " 30"}; 815146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDateStrWidth = computeMaxStringWidth(0, dateStrs, p); 8163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 817146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDateStrWidth += computeMaxStringWidth(0, mDayStrs, p); 818146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 819e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextSize(HOURS_TEXT_SIZE); 820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(null); 82161a2e87e7412281d17e86ccff4352cbf32fe77e7Michael Chan handleOnResume(); 822146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 823e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mAmString = DateUtils.getAMPMString(Calendar.AM).toUpperCase(); 824e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mPmString = DateUtils.getAMPMString(Calendar.PM).toUpperCase(); 825146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] ampm = {mAmString, mPmString}; 826e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextSize(AMPM_TEXT_SIZE); 827e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mHoursWidth = Math.max(HOURS_MARGIN, computeMaxStringWidth(mHoursWidth, ampm, p) 828e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik + HOURS_RIGHT_MARGIN); 8298f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mHoursWidth = Math.max(MIN_HOURS_WIDTH, mHoursWidth); 830146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 831146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project LayoutInflater inflater; 832146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 833146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView = inflater.inflate(R.layout.bubble_event, null); 834146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView.setLayoutParams(new ViewGroup.LayoutParams( 835df279e3f9d5b0f189f812c52aca78d18178e4445Romain Guy ViewGroup.LayoutParams.MATCH_PARENT, 836146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ViewGroup.LayoutParams.WRAP_CONTENT)); 837146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup = new PopupWindow(context); 838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setContentView(mPopupView); 839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Resources.Theme dialogTheme = getResources().newTheme(); 840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dialogTheme.applyStyle(android.R.style.Theme_Dialog, true); 841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TypedArray ta = dialogTheme.obtainStyledAttributes(new int[] { 842146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project android.R.attr.windowBackground }); 843146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setBackgroundDrawable(ta.getDrawable(0)); 844146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ta.recycle(); 845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Enable touching the popup window 847146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView.setOnClickListener(this); 848cd405a28e6821b116dcf3c531805d0c90b6cc08cErik // Catch long clicks for creating a new event 849cd405a28e6821b116dcf3c531805d0c90b6cc08cErik setOnLongClickListener(this); 850146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 851731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate = new Time(Utils.getTimeZone(context, mTZUpdater)); 852146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = System.currentTimeMillis(); 853146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.set(millis); 854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour = new int[mNumDays]; 856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent = new boolean[mNumDays]; 85702041687c35441e8a21cb763f1fc3a26525292efDavid Brown 85802041687c35441e8a21cb763f1fc3a26525292efDavid Brown // mLines is the array of points used with Canvas.drawLines() in 85902041687c35441e8a21cb763f1fc3a26525292efDavid Brown // drawGridBackground() and drawAllDayEvents(). Its size depends 86002041687c35441e8a21cb763f1fc3a26525292efDavid Brown // on the max number of lines that can ever be drawn by any single 86102041687c35441e8a21cb763f1fc3a26525292efDavid Brown // drawLines() call in either of those methods. 86202041687c35441e8a21cb763f1fc3a26525292efDavid Brown final int maxGridLines = (24 + 1) // max horizontal lines we might draw 863e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik + (mNumDays + 1); // max vertical lines we might draw 86402041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines = new float[maxGridLines * 4]; 865146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 866146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 867146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 868146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * This is called when the popup window is pressed. 869146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 870146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void onClick(View v) { 871146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (v == mPopupView) { 872146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pretend it was a trackball click because that will always 873146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // jump to the "View event" screen. 874146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball */); 875146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 876146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 877146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 87861a2e87e7412281d17e86ccff4352cbf32fe77e7Michael Chan public void handleOnResume() { 879aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan initAccessibilityVariables(); 880cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan if(Utils.getSharedPreference(mContext, OtherPreferences.KEY_OTHER_1, false)) { 881cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan mFutureBgColor = 0; 882cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } else { 883cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan mFutureBgColor = mFutureBgColorRes; 884cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } 885ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mIs24HourFormat = DateFormat.is24HourFormat(mContext); 88669ab334d6988eda70ba53618506d23ebf7d7b405Erik mHourStrs = mIs24HourFormat ? CalendarData.s24Hours : CalendarData.s12HoursNoAmPm; 88761a2e87e7412281d17e86ccff4352cbf32fe77e7Michael Chan mFirstDayOfWeek = Utils.getFirstDayOfWeek(mContext); 8889ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan mLastSelectionDay = 0; 8899ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan mLastSelectionHour = 0; 8909ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan mLastSelectedEvent = null; 891f7cf45455ce8cc5588479dcbb5d876f7638f79dcRoboErik mSelectionMode = SELECTION_HIDDEN; 89269ab334d6988eda70ba53618506d23ebf7d7b405Erik } 89369ab334d6988eda70ba53618506d23ebf7d7b405Erik 894aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan private void initAccessibilityVariables() { 895aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mAccessibilityMgr = (AccessibilityManager) mContext 896aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan .getSystemService(Service.ACCESSIBILITY_SERVICE); 897aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mIsAccessibilityEnabled = mAccessibilityMgr != null && mAccessibilityMgr.isEnabled(); 898aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mTouchExplorationEnabled = isTouchExplorationEnabled(); 899aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 900aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan 901146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 902146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Returns the start of the selected time in milliseconds since the epoch. 903146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return selected time in UTC milliseconds since the epoch. 905146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 906146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long getSelectedTimeInMillis() { 907146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 908146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 909146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 910146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 911146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 912146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 913146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 914146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time.normalize(true /* ignore isDst */); 915146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 916146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 917146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time getSelectedTime() { 918146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 919146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 920146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 921146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 922146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 923146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 924146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 925146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.normalize(true /* ignore isDst */); 926146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time; 927146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 928146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 929146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Returns the start of the selected time in minutes since midnight, 931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * local time. The derived class must ensure that this is consistent 932146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * with the return value from getSelectedTimeInMillis(). 933146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 934146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int getSelectedMinutesSinceMidnight() { 935146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return mSelectionHour * MINUTES_PER_HOUR; 936146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 937146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 93846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int getFirstVisibleHour() { 93946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return mFirstHour; 94046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 94146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 94246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan void setFirstVisibleHour(int firstHour) { 94346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mFirstHour = firstHour; 94446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mFirstHourOffset = 0; 94546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 94646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 9475b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void setSelected(Time time, boolean ignoreTime, boolean animateToday) { 948146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.set(time); 949146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mBaseDate.hour; 950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 951146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 952146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = mBaseDate.toMillis(false /* use isDst */); 953146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = Time.getJulianDay(millis, mBaseDate.gmtoff); 954146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 956146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 95746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int gotoY = Integer.MIN_VALUE; 95846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 95946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (!ignoreTime && mGridAreaHeight != -1) { 96046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int lastHour = 0; 96146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 96246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mBaseDate.hour < mFirstHour) { 96346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Above visible region 96446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan gotoY = mBaseDate.hour * (mCellHeight + HOUR_GAP); 96546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 96646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan lastHour = (mGridAreaHeight - mFirstHourOffset) / (mCellHeight + HOUR_GAP) 96746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan + mFirstHour; 96846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 96946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mBaseDate.hour >= lastHour) { 97046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Below visible region 97146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 97246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // target hour + 1 (to give it room to see the event) - 97346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // grid height (to get the y of the top of the visible 97446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // region) 97555a26d7062d5aa1a1b001b7271bb137276ab807eErik gotoY = (int) ((mBaseDate.hour + 1 + mBaseDate.minute / 60.0f) 97646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * (mCellHeight + HOUR_GAP) - mGridAreaHeight); 97746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 97846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 97946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 98046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) { 98146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan Log.e(TAG, "Go " + gotoY + " 1st " + mFirstHour + ":" + mFirstHourOffset + "CH " 98246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan + (mCellHeight + HOUR_GAP) + " lh " + lastHour + " gh " + mGridAreaHeight 98346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan + " ymax " + mMaxViewStartY); 98446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 98546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 98646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (gotoY > mMaxViewStartY) { 98746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan gotoY = mMaxViewStartY; 98846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else if (gotoY < 0 && gotoY != Integer.MIN_VALUE) { 98946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan gotoY = 0; 99046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 99146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 99246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = true; 996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 99746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 9985b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik boolean delayAnimateToday = false; 99946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (gotoY != Integer.MIN_VALUE) { 10005b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik ValueAnimator scrollAnim = ObjectAnimator.ofInt(this, "viewStartY", mViewStartY, gotoY); 10015b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik scrollAnim.setDuration(GOTO_SCROLL_DURATION); 100246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan scrollAnim.setInterpolator(new AccelerateDecelerateInterpolator()); 100346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan scrollAnim.addListener(mAnimatorListener); 100446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan scrollAnim.start(); 10055b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik delayAnimateToday = true; 10065b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 10075b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (animateToday) { 10085b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik synchronized (mTodayAnimatorListener) { 10095b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mTodayAnimator != null) { 10105b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.removeAllListeners(); 10115b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.cancel(); 10125b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 10135b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator = ObjectAnimator.ofInt(this, "animateTodayAlpha", 10145b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateTodayAlpha, 255); 10155b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateToday = true; 10165b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimatorListener.setFadingIn(true); 10175b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimatorListener.setAnimator(mTodayAnimator); 10185b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.addListener(mTodayAnimatorListener); 10195b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.setDuration(150); 10205b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (delayAnimateToday) { 10215b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.setStartDelay(GOTO_SCROLL_DURATION); 10225b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 10235b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.start(); 10245b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 102546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 1026aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan sendAccessibilityEventAsNeeded(false); 102746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 102846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 102946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void setViewStartY(int viewStartY) { 103046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (viewStartY > mMaxViewStartY) { 103146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan viewStartY = mMaxViewStartY; 103246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 103346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 103446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mViewStartY = viewStartY; 103546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 103646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan computeFirstHour(); 103746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan invalidate(); 1038146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1039146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 10405b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void setAnimateTodayAlpha(int todayAlpha) { 10415b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateTodayAlpha = todayAlpha; 10425b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik invalidate(); 10435b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 10445b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 1045146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public Time getSelectedDay() { 1046146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 1047146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 1048146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 1049146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1050146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 1051146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 1052146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 1053146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.normalize(true /* ignore isDst */); 1054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time; 1055146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1056146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1057eaafa2b48be7194a61754604ae37b3d62e9118d8Erik public void updateTitle() { 1058eaafa2b48be7194a61754604ae37b3d62e9118d8Erik Time start = new Time(mBaseDate); 1059eaafa2b48be7194a61754604ae37b3d62e9118d8Erik start.normalize(true); 1060eaafa2b48be7194a61754604ae37b3d62e9118d8Erik Time end = new Time(start); 1061eaafa2b48be7194a61754604ae37b3d62e9118d8Erik end.monthDay += mNumDays - 1; 1062eaafa2b48be7194a61754604ae37b3d62e9118d8Erik // Move it forward one minute so the formatter doesn't lose a day 1063eaafa2b48be7194a61754604ae37b3d62e9118d8Erik end.minute += 1; 1064eaafa2b48be7194a61754604ae37b3d62e9118d8Erik end.normalize(true); 1065eaafa2b48be7194a61754604ae37b3d62e9118d8Erik 10669e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan long formatFlags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR; 10679e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan if (mNumDays != 1) { 10689e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan // Don't show day of the month if for multi-day view 10699e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan formatFlags |= DateUtils.FORMAT_NO_MONTH_DAY; 10709e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan 10719e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan // Abbreviate the month if showing multiple months 10729e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan if (start.month != end.month) { 10739e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan formatFlags |= DateUtils.FORMAT_ABBREV_MONTH; 10749e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan } 10759e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan } 10769e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan 1077f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mController.sendEvent(this, EventType.UPDATE_TITLE, start, end, null, -1, ViewType.CURRENT, 10789e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan formatFlags, null, null); 1079eaafa2b48be7194a61754604ae37b3d62e9118d8Erik } 1080eaafa2b48be7194a61754604ae37b3d62e9118d8Erik 108183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan /** 1082487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * return a negative number if "time" is comes before the visible time 1083487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * range, a positive number if "time" is after the visible time range, and 0 1084487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * if it is in the visible time range. 108583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan */ 1086487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan public int compareToVisibleTimeRange(Time time) { 1087487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 1088487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedHour = mBaseDate.hour; 1089487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedMinute = mBaseDate.minute; 1090487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedSec = mBaseDate.second; 1091487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 1092487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.hour = 0; 1093487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.minute = 0; 1094487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.second = 0; 1095487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 1096030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) { 1097030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown Log.d(TAG, "Begin " + mBaseDate.toString()); 1098030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown Log.d(TAG, "Diff " + time.toString()); 1099030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown } 1100487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 110183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan // Compare beginning of range 110283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan int diff = Time.compare(time, mBaseDate); 1103487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (diff > 0) { 1104487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // Compare end of range 1105487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.monthDay += mNumDays; 1106487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.normalize(true); 1107487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = Time.compare(time, mBaseDate); 1108487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 1109030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "End " + mBaseDate.toString()); 1110487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 1111487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.monthDay -= mNumDays; 1112487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.normalize(true); 1113487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (diff < 0) { 1114487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // in visible time 1115487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = 0; 1116487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } else if (diff == 0) { 1117487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // Midnight of following day 1118487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = 1; 1119487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 112083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 112183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 1122030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "Diff: " + diff); 112383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 1124487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.hour = savedHour; 1125487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.minute = savedMinute; 1126487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.second = savedSec; 1127487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan return diff; 112883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 112983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 1130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void recalc() { 1131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Set the base date to the beginning of the week if we are displaying 1132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // 7 days at a time. 1133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 7) { 11346d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan adjustToBeginningOfWeek(mBaseDate); 1135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final long start = mBaseDate.toMillis(false /* use isDst */); 1138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstJulianDay = Time.getJulianDay(start, mBaseDate.gmtoff); 1139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastJulianDay = mFirstJulianDay + mNumDays - 1; 1140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mMonthLength = mBaseDate.getActualMaximum(Time.MONTH_DAY); 1142487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstVisibleDate = mBaseDate.monthDay; 1143487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstVisibleDayOfWeek = mBaseDate.weekDay; 1144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 11466d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private void adjustToBeginningOfWeek(Time time) { 11476d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan int dayOfWeek = time.weekDay; 11486d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan int diff = dayOfWeek - mFirstDayOfWeek; 11496d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (diff != 0) { 11506d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (diff < 0) { 11516d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan diff += 7; 11526d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 11536d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan time.monthDay -= diff; 11546d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan time.normalize(true /* ignore isDst */); 11556d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 11566d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 11576d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 1158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected void onSizeChanged(int width, int height, int oldw, int oldh) { 1160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewWidth = width; 1161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewHeight = height; 1162433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop.setSize(mViewWidth, mViewHeight); 1163433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom.setSize(mViewWidth, mViewHeight); 1164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int gridAreaWidth = width - mHoursWidth; 1165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mCellWidth = (gridAreaWidth - (mNumDays * DAY_GAP)) / mNumDays; 1166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1167d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan // This would be about 1 day worth in a 7 day view 1168d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan mHorizontalSnapBackThreshold = width / 7; 1169d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan 1170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = new Paint(); 1171e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextSize(HOURS_TEXT_SIZE); 1172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHoursTextHeight = (int) Math.abs(p.ascent()); 1173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project remeasure(width, height); 1174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 117646b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa /** 117746b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa * Measures the space needed for various parts of the view after 117846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa * loading new events. This can change if there are all-day events. 117946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa */ 1180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void remeasure(int width, int height) { 11812fda24534978f55711526dbde747aa50d68dec40RoboErik // Shrink to fit available space but make sure we can display at least two events 11822fda24534978f55711526dbde747aa50d68dec40RoboErik MAX_UNEXPANDED_ALLDAY_HEIGHT = (int) (MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT * 4); 11832fda24534978f55711526dbde747aa50d68dec40RoboErik MAX_UNEXPANDED_ALLDAY_HEIGHT = Math.min(MAX_UNEXPANDED_ALLDAY_HEIGHT, height / 6); 11842fda24534978f55711526dbde747aa50d68dec40RoboErik MAX_UNEXPANDED_ALLDAY_HEIGHT = Math.max(MAX_UNEXPANDED_ALLDAY_HEIGHT, 11852fda24534978f55711526dbde747aa50d68dec40RoboErik (int) MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT * 2); 11862fda24534978f55711526dbde747aa50d68dec40RoboErik mMaxUnexpandedAlldayEventCount = 11872fda24534978f55711526dbde747aa50d68dec40RoboErik (int) (MAX_UNEXPANDED_ALLDAY_HEIGHT / MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT); 1188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear the array of earliest start times, and the array 1190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // indicating presence of an all-day event. 1191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++) { 1192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[day] = 25; // some big number 1193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent[day] = false; 1194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 11962fda24534978f55711526dbde747aa50d68dec40RoboErik int maxAllDayEvents = mMaxAlldayEvents; 1197c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa 11982fda24534978f55711526dbde747aa50d68dec40RoboErik // The min is where 24 hours cover the entire visible area 11997939fa59d64c1e6ac95f352e24d761dbacf67547RoboErik mMinCellHeight = Math.max((height - DAY_HEADER_HEIGHT) / 24, (int) MIN_EVENT_HEIGHT); 12002fda24534978f55711526dbde747aa50d68dec40RoboErik if (mCellHeight < mMinCellHeight) { 12012fda24534978f55711526dbde747aa50d68dec40RoboErik mCellHeight = mMinCellHeight; 1202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 12049c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan // Calculate mAllDayHeight 12053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mFirstCell = DAY_HEADER_HEIGHT; 1206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int allDayHeight = 0; 1207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxAllDayEvents > 0) { 12082fda24534978f55711526dbde747aa50d68dec40RoboErik int maxAllAllDayHeight = height - DAY_HEADER_HEIGHT - MIN_HOURS_HEIGHT; 1209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is at most one all-day event per day, then use less 1210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // space (but more than the space for a single event). 1211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxAllDayEvents == 1) { 1212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project allDayHeight = SINGLE_ALLDAY_HEIGHT; 12132fda24534978f55711526dbde747aa50d68dec40RoboErik } else if (maxAllDayEvents <= mMaxUnexpandedAlldayEventCount){ 1214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allow the all-day area to grow in height depending on the 1215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // number of all-day events we need to show, up to a limit. 1216f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan allDayHeight = maxAllDayEvents * MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 12172fda24534978f55711526dbde747aa50d68dec40RoboErik if (allDayHeight > MAX_UNEXPANDED_ALLDAY_HEIGHT) { 12182fda24534978f55711526dbde747aa50d68dec40RoboErik allDayHeight = MAX_UNEXPANDED_ALLDAY_HEIGHT; 12192fda24534978f55711526dbde747aa50d68dec40RoboErik } 12202fda24534978f55711526dbde747aa50d68dec40RoboErik } else { 12212fda24534978f55711526dbde747aa50d68dec40RoboErik // if we have more than the magic number, check if we're animating 12222fda24534978f55711526dbde747aa50d68dec40RoboErik // and if not adjust the sizes appropriately 12232fda24534978f55711526dbde747aa50d68dec40RoboErik if (mAnimateDayHeight != 0) { 12242fda24534978f55711526dbde747aa50d68dec40RoboErik // Don't shrink the space past the final allDay space. The animation 12252fda24534978f55711526dbde747aa50d68dec40RoboErik // continues to hide the last event so the more events text can 12262fda24534978f55711526dbde747aa50d68dec40RoboErik // fade in. 12272fda24534978f55711526dbde747aa50d68dec40RoboErik allDayHeight = Math.max(mAnimateDayHeight, MAX_UNEXPANDED_ALLDAY_HEIGHT); 12282fda24534978f55711526dbde747aa50d68dec40RoboErik } else { 12292fda24534978f55711526dbde747aa50d68dec40RoboErik // Try to fit all the events in 12302fda24534978f55711526dbde747aa50d68dec40RoboErik allDayHeight = (int) (maxAllDayEvents * MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT); 12312fda24534978f55711526dbde747aa50d68dec40RoboErik // But clip the area depending on which mode we're in 12322fda24534978f55711526dbde747aa50d68dec40RoboErik if (!mShowAllAllDayEvents && allDayHeight > MAX_UNEXPANDED_ALLDAY_HEIGHT) { 1233e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik allDayHeight = (int) (mMaxUnexpandedAlldayEventCount * 1234e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT); 12352fda24534978f55711526dbde747aa50d68dec40RoboErik } else if (allDayHeight > maxAllAllDayHeight) { 12362fda24534978f55711526dbde747aa50d68dec40RoboErik allDayHeight = maxAllAllDayHeight; 12372fda24534978f55711526dbde747aa50d68dec40RoboErik } 1238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 12403eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mFirstCell = DAY_HEADER_HEIGHT + allDayHeight + ALLDAY_TOP_MARGIN; 1241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 12422fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = false; 1243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 12442fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayHeight = allDayHeight; 1245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mGridAreaHeight = height - mFirstCell; 1247d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 12482fda24534978f55711526dbde747aa50d68dec40RoboErik // Set up the expand icon position 1249e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int allDayIconWidth = mExpandAlldayDrawable.getIntrinsicWidth(); 1250e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mExpandAllDayRect.left = Math.max((mHoursWidth - allDayIconWidth) / 2, 1251e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik EVENT_ALL_DAY_TEXT_LEFT_MARGIN); 1252e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mExpandAllDayRect.right = Math.min(mExpandAllDayRect.left + allDayIconWidth, mHoursWidth 1253e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik - EVENT_ALL_DAY_TEXT_RIGHT_MARGIN); 1254cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mExpandAllDayRect.bottom = mFirstCell - EXPAND_ALL_DAY_BOTTOM_MARGIN; 1255e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mExpandAllDayRect.top = mExpandAllDayRect.bottom 1256e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik - mExpandAlldayDrawable.getIntrinsicHeight(); 1257e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 125846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mNumHours = mGridAreaHeight / (mCellHeight + HOUR_GAP); 1259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setHourHeight(mCellHeight); 1260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 126127d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa final long minimumDurationMillis = (long) 126227d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa (MIN_EVENT_HEIGHT * DateUtils.MINUTE_IN_MILLIS / (mCellHeight / 60.0f)); 12632fda24534978f55711526dbde747aa50d68dec40RoboErik Event.computePositions(mEvents, minimumDurationMillis); 126446b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa 1265c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Compute the top of our reachable view 1266c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mMaxViewStartY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP) - mGridAreaHeight; 1267d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 1268d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.e(TAG, "mViewStartY: " + mViewStartY); 1269d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.e(TAG, "mMaxViewStartY: " + mMaxViewStartY); 1270d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 1271d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mViewStartY > mMaxViewStartY) { 1272d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = mMaxViewStartY; 1273d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan computeFirstHour(); 1274d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 1275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour == -1) { 1277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initFirstHour(); 1278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = 0; 1279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // When we change the base date, the number of all-day events may 1282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // change and that changes the cell height. When we switch dates, 1283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // we use the mFirstHourOffset from the previous view, but that may 1284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // be too large for the new view if the cell height is smaller. 1285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHourOffset >= mCellHeight + HOUR_GAP) { 1286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = mCellHeight + HOUR_GAP - 1; 1287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mFirstHour * (mCellHeight + HOUR_GAP) - mFirstHourOffset; 1289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 129046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final int eventAreaWidth = mNumDays * (mCellWidth + DAY_GAP); 1291666fc5e8ddbac15c951aad738bd818ee307eae42Erik //When we get new events we don't want to dismiss the popup unless the event changes 1292666fc5e8ddbac15c951aad738bd818ee307eae42Erik if (mSelectedEvent != null && mLastPopupEventID != mSelectedEvent.id) { 1293666fc5e8ddbac15c951aad738bd818ee307eae42Erik mPopup.dismiss(); 1294666fc5e8ddbac15c951aad738bd818ee307eae42Erik } 1295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setWidth(eventAreaWidth - 20); 1296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); 1297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Initialize the state for another view. The given view is one that has 1301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * its own bitmap and will use an animation to replace the current view. 1302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The current view and new view are either both Week views or both Day 1303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * views. They differ in their base date. 1304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 1305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param view the view to initialize. 1306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1307d190418220467c02327dd9b3ae1eae238889720bMichael Chan private void initView(DayView view) { 1308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionHour = mSelectionHour; 1309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectedEvents.clear(); 1310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mComputeSelectedEvents = true; 1311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mFirstHour = mFirstHour; 1312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mFirstHourOffset = mFirstHourOffset; 1313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.remeasure(getWidth(), getHeight()); 13142fda24534978f55711526dbde747aa50d68dec40RoboErik view.initAllDayHeights(); 1315e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 1316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectedEvent = null; 1317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mPrevSelectedEvent = null; 1318487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan view.mFirstDayOfWeek = mFirstDayOfWeek; 1319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (view.mEvents.size() > 0) { 13202fda24534978f55711526dbde747aa50d68dec40RoboErik view.mSelectionAllday = mSelectionAllday; 1321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 13222fda24534978f55711526dbde747aa50d68dec40RoboErik view.mSelectionAllday = false; 1323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Redraw the screen so that the selection box will be redrawn. We may 1326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // have scrolled to a different part of the day in some other view 1327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // so the selection box in this view may no longer be visible. 1328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.recalc(); 1329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Switch to another view based on what was selected (an event or a free 1333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * slot) and how it was selected (by touch or by trackball). 1334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 1335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param trackBallSelection true if the selection was made using the 1336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * trackball. 1337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void switchViews(boolean trackBallSelection) { 1339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 1340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 1342666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays > 1) { 1344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the Week view. 1345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // With touch, we always switch to Day/Agenda View 1346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // With track ball, if we selected a free slot, then create an event. 1347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected a specific event, switch to EventInfo view. 1348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (trackBallSelection) { 1349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 1350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EditEvent view 1351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 1352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 1353edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan long extraLong = 0; 1354edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan if (mSelectionAllday) { 1355edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan extraLong = CalendarController.EXTRA_CREATE_ALL_DAY; 1356edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan } 1357edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan mController.sendEventRelatedEventWithExtra(this, EventType.CREATE_EVENT, -1, 1358edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan startMillis, endMillis, -1, -1, extraLong, -1); 1359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1360aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (mIsAccessibilityEnabled) { 1361aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mAccessibilityMgr.interrupt(); 1362aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 1363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EventInfo view 13649e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 136587f993ff96172f508d3f241f8a425f953c7eb739RoboErik selectedEvent.startMillis, selectedEvent.endMillis, 0, 0, 136687f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis()); 1367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This was a touch selection. If the touch selected a single 1370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // unambiguous event, then view that event. Otherwise go to 1371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Day/Agenda view. 1372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvents.size() == 1) { 1373aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (mIsAccessibilityEnabled) { 1374aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mAccessibilityMgr.interrupt(); 1375aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 13769e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 137787f993ff96172f508d3f241f8a425f953c7eb739RoboErik selectedEvent.startMillis, selectedEvent.endMillis, 0, 0, 137887f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis()); 1379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the Day view. 1383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected a free slot, then create an event. 1384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected an event, then go to the EventInfo view. 1385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 1386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EditEvent view 1387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 1388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 1389edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan long extraLong = 0; 1390edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan if (mSelectionAllday) { 1391edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan extraLong = CalendarController.EXTRA_CREATE_ALL_DAY; 1392edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan } 1393edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan mController.sendEventRelatedEventWithExtra(this, EventType.CREATE_EVENT, -1, 1394edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan startMillis, endMillis, -1, -1, extraLong, -1); 1395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1396aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (mIsAccessibilityEnabled) { 1397aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mAccessibilityMgr.interrupt(); 1398aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 13999e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 140087f993ff96172f508d3f241f8a425f953c7eb739RoboErik selectedEvent.startMillis, selectedEvent.endMillis, 0, 0, 140187f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis()); 1402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 1408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 1409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long duration = event.getEventTime() - event.getDownTime(); 1410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (keyCode) { 1412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 1413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_HIDDEN) { 1414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Don't do anything unless the selection is visible. 1415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_PRESSED) { 1419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This was the first press when there was nothing selected. 1420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Change the selection from the "pressed" state to the 1421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the "selected" state. We treat short-press and 1422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // long-press the same here because nothing was selected. 1423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check the duration to determine if this was a short press 1429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (duration < ViewConfiguration.getLongPressTimeout()) { 1430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball */); 1431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 1433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project performLongClick(); 1435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1437ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// case KeyEvent.KEYCODE_BACK: 1438ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// if (event.isTracking() && !event.isCanceled()) { 1439ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mPopup.dismiss(); 1440ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.finish(); 1441ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// return true; 1442ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// } 1443ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// break; 1444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyUp(keyCode, event); 1446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 1450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_HIDDEN) { 1451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT 1452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_UP 1453146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { 1454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Display the selection box but don't move or select it 1455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on this key press. 1456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 1460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Display the selection box but don't select it 1461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on this key press. 1462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_PRESSED; 1463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 1470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean redraw; 1471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectionDay = mSelectionDay; 1472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (keyCode) { 147446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DEL: 147546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Delete the selected event, if any 147646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan Event selectedEvent = mSelectedEvent; 147746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (selectedEvent == null) { 147846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return false; 147946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 148046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mPopup.dismiss(); 148146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 1482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 148346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan long begin = selectedEvent.startMillis; 148446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan long end = selectedEvent.endMillis; 148546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan long id = selectedEvent.id; 148646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mDeleteEventHelper.delete(begin, end, id, -1); 1487b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan return true; 148846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_ENTER: 148946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan switchViews(true /* trackball or keyboard */); 149046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 149146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_BACK: 149246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (event.getRepeatCount() == 0) { 149346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan event.startTracking(); 149446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 149546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 149646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return super.onKeyDown(keyCode, event); 149746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_LEFT: 149846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 149946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvent = mSelectedEvent.nextLeft; 150046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 150146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 150246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 150346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan selectionDay -= 1; 150446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 150546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 150646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 150846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_RIGHT: 150946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 151046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvent = mSelectedEvent.nextRight; 151146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 151246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 151346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 151446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan selectionDay += 1; 151546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 151646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 151746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1518146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 151946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_UP: 152046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 152146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvent = mSelectedEvent.nextUp; 1522146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 152346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 152446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 15252fda24534978f55711526dbde747aa50d68dec40RoboErik if (!mSelectionAllday) { 152646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectionHour -= 1; 152746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan adjustHourSelection(); 152846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvents.clear(); 152946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mComputeSelectedEvents = true; 153046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 153146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 153246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 153346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 153546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_DOWN: 153646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 153746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvent = mSelectedEvent.nextDown; 1538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 153946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 154046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 15412fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSelectionAllday) { 15422fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = false; 154346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 154446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectionHour++; 154546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan adjustHourSelection(); 154646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvents.clear(); 154746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mComputeSelectedEvents = true; 154846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 154946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 155046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 155146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 155346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan default: 155446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return super.onKeyDown(keyCode, event); 1555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((selectionDay < mFirstJulianDay) || (selectionDay > mLastJulianDay)) { 1558d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getNextView(); 1559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time date = view.mBaseDate; 1560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.set(mBaseDate); 1561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectionDay < mFirstJulianDay) { 1562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay -= mNumDays; 1563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay += mNumDays; 1565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.normalize(true /* ignore isDst */); 1567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = selectionDay; 1568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initView(view); 157083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 157183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time end = new Time(date); 157283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan end.monthDay += mNumDays - 1; 15733458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan mController.sendEvent(this, EventType.GO_TO, date, end, -1, ViewType.CURRENT); 1574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 157604b288958078f8b29870dcbb2239df448c559610Erik if (mSelectionDay != selectionDay) { 157704b288958078f8b29870dcbb2239df448c559610Erik Time date = new Time(mBaseDate); 157804b288958078f8b29870dcbb2239df448c559610Erik date.setJulianDay(selectionDay); 157904b288958078f8b29870dcbb2239df448c559610Erik date.hour = mSelectionHour; 158004b288958078f8b29870dcbb2239df448c559610Erik mController.sendEvent(this, EventType.GO_TO, date, date, -1, ViewType.CURRENT); 158104b288958078f8b29870dcbb2239df448c559610Erik } 1582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = selectionDay; 1583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 15858307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik mUpdateToast = true; 1586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (redraw) { 1588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyDown(keyCode, event); 1593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 15959ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 15969ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan @Override 15979ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan public boolean onHoverEvent(MotionEvent event) { 15989ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) { 15999ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan int action = event.getAction(); 16009ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan switch (action) { 16019ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan case MotionEvent.ACTION_HOVER_ENTER: 16029ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan Log.e(TAG, "ACTION_HOVER_ENTER"); 16039ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan break; 16049ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan case MotionEvent.ACTION_HOVER_MOVE: 16059ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan Log.e(TAG, "ACTION_HOVER_MOVE"); 16069ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan break; 16079ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan case MotionEvent.ACTION_HOVER_EXIT: 16089ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan Log.e(TAG, "ACTION_HOVER_EXIT"); 16099ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan break; 16109ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan default: 16119ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan Log.e(TAG, "Unknown hover event action. " + event); 16129ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 16139ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 16149ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 16159ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan // Mouse also generates hover events 16169ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan // Send accessibility events if accessibility and exploration are on. 16179ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (!mTouchExplorationEnabled) { 16189ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan return super.onHoverEvent(event); 1619259b8f9a21fffd3858218581e9daaf689b6b888fErik } 16209ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (event.getAction() != MotionEvent.ACTION_HOVER_EXIT) { 16219ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan setSelectionFromPosition((int) event.getX(), (int) event.getY()); 16229ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan invalidate(); 16239ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 16249ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan return true; 1625259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1626259b8f9a21fffd3858218581e9daaf689b6b888fErik 16279ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan private boolean isTouchExplorationEnabled() { 1628aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan return mIsAccessibilityEnabled && mAccessibilityMgr.isTouchExplorationEnabled(); 16299ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 1630259b8f9a21fffd3858218581e9daaf689b6b888fErik 1631aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan private void sendAccessibilityEventAsNeeded(boolean speakEvents) { 1632aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (!mIsAccessibilityEnabled) { 1633be569a176153e0b4b4606a022ab30cf2f5bf719dRoboErik return; 1634be569a176153e0b4b4606a022ab30cf2f5bf719dRoboErik } 16359ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan boolean dayChanged = mLastSelectionDay != mSelectionDay; 16369ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan boolean hourChanged = mLastSelectionHour != mSelectionHour; 16379ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (dayChanged || hourChanged || mLastSelectedEvent != mSelectedEvent) { 16389ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan mLastSelectionDay = mSelectionDay; 16399ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan mLastSelectionHour = mSelectionHour; 16409ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan mLastSelectedEvent = mSelectedEvent; 16419ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 16429ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan StringBuilder b = new StringBuilder(); 16439ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 16449ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan // Announce only the changes i.e. day or hour or both 16459ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (dayChanged) { 16469ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan b.append(getSelectedTime().format("%A ")); 16479ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 16489ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (hourChanged) { 16499ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan b.append(getSelectedTime().format(mIs24HourFormat ? "%k" : "%l%p")); 16509ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 1651aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (dayChanged || hourChanged) { 1652aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan b.append(PERIOD_SPACE); 1653aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 16549ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 1655aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (speakEvents) { 1656aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (mEventCountTemplate == null) { 1657aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mEventCountTemplate = mContext.getString(R.string.template_announce_item_index); 1658aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 1659aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan 1660aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan // Read out the relevant event(s) 1661aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan int numEvents = mSelectedEvents.size(); 1662aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (numEvents > 0) { 1663aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (mSelectedEvent == null) { 1664aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan // Read out all the events 1665aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan int i = 1; 1666aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan for (Event calEvent : mSelectedEvents) { 1667aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (numEvents > 1) { 1668aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan // Read out x of numEvents if there are more than one event 1669aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mStringBuilder.setLength(0); 1670aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan b.append(mFormatter.format(mEventCountTemplate, i++, numEvents)); 1671aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan b.append(" "); 1672aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 1673aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan appendEventAccessibilityString(b, calEvent); 1674aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 1675aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } else { 16769ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (numEvents > 1) { 16779ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan // Read out x of numEvents if there are more than one event 16789ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan mStringBuilder.setLength(0); 1679aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan b.append(mFormatter.format(mEventCountTemplate, mSelectedEvents 1680aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan .indexOf(mSelectedEvent) + 1, numEvents)); 16819ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan b.append(" "); 16829ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 1683aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan appendEventAccessibilityString(b, mSelectedEvent); 1684259b8f9a21fffd3858218581e9daaf689b6b888fErik } 16859ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } else { 1686aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan b.append(mCreateNewEventString); 1687259b8f9a21fffd3858218581e9daaf689b6b888fErik } 16889ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 16899ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 1690aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (dayChanged || hourChanged || speakEvents) { 1691aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan AccessibilityEvent event = AccessibilityEvent 1692d01a7b6aab2bfe79e60359137d1bfd7ec9672368Michael Chan .obtain(AccessibilityEvent.TYPE_VIEW_FOCUSED); 1693aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan CharSequence msg = b.toString(); 1694aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan event.getText().add(msg); 1695aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan event.setAddedCount(msg.length()); 1696aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan sendAccessibilityEventUnchecked(event); 1697aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 1698259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1699259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1700259b8f9a21fffd3858218581e9daaf689b6b888fErik 1701259b8f9a21fffd3858218581e9daaf689b6b888fErik /** 1702259b8f9a21fffd3858218581e9daaf689b6b888fErik * @param b 1703259b8f9a21fffd3858218581e9daaf689b6b888fErik * @param calEvent 1704259b8f9a21fffd3858218581e9daaf689b6b888fErik */ 1705259b8f9a21fffd3858218581e9daaf689b6b888fErik private void appendEventAccessibilityString(StringBuilder b, Event calEvent) { 1706259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(calEvent.getTitleAndLocation()); 1707259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(PERIOD_SPACE); 1708259b8f9a21fffd3858218581e9daaf689b6b888fErik String when; 1709259b8f9a21fffd3858218581e9daaf689b6b888fErik int flags = DateUtils.FORMAT_SHOW_DATE; 1710259b8f9a21fffd3858218581e9daaf689b6b888fErik if (calEvent.allDay) { 1711259b8f9a21fffd3858218581e9daaf689b6b888fErik flags |= DateUtils.FORMAT_UTC | DateUtils.FORMAT_SHOW_WEEKDAY; 1712259b8f9a21fffd3858218581e9daaf689b6b888fErik } else { 1713259b8f9a21fffd3858218581e9daaf689b6b888fErik flags |= DateUtils.FORMAT_SHOW_TIME; 1714259b8f9a21fffd3858218581e9daaf689b6b888fErik if (DateFormat.is24HourFormat(mContext)) { 1715259b8f9a21fffd3858218581e9daaf689b6b888fErik flags |= DateUtils.FORMAT_24HOUR; 1716259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1717259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1718259b8f9a21fffd3858218581e9daaf689b6b888fErik when = Utils.formatDateRange(mContext, calEvent.startMillis, calEvent.endMillis, flags); 1719259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(when); 1720259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(PERIOD_SPACE); 1721259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1722259b8f9a21fffd3858218581e9daaf689b6b888fErik 17236d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private class GotoBroadcaster implements Animation.AnimationListener { 17246d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private final int mCounter; 17256d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private final Time mStart; 17266d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private final Time mEnd; 17276d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 17286d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public GotoBroadcaster(Time start, Time end) { 17296d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan mCounter = ++sCounter; 17306d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan mStart = start; 17316d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan mEnd = end; 17326d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 17336d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 17346d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan @Override 17356d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public void onAnimationEnd(Animation animation) { 1736f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan DayView view = (DayView) mViewSwitcher.getCurrentView(); 1737f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan view.mViewStartX = 0; 1738f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan view = (DayView) mViewSwitcher.getNextView(); 1739f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan view.mViewStartX = 0; 1740f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan 17416d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (mCounter == sCounter) { 1742f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mController.sendEvent(this, EventType.GO_TO, mStart, mEnd, null, -1, 1743f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan ViewType.CURRENT, CalendarController.EXTRA_GOTO_DATE, null, null); 17446d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 17456d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 17466d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 17476d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan @Override 17486d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public void onAnimationRepeat(Animation animation) { 17496d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 17506d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 17516d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan @Override 17526d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public void onAnimationStart(Animation animation) { 17536d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 17546d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 17556d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 17562c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan private View switchViews(boolean forward, float xOffSet, float width, float velocity) { 175795d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan mAnimationDistance = width - xOffSet; 175895d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan if (DEBUG) { 175995d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan Log.d(TAG, "switchViews(" + forward + ") O:" + xOffSet + " Dist:" + mAnimationDistance); 176095d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan } 176195d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan 1762ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float progress = Math.abs(xOffSet) / width; 1763ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (progress > 1.0f) { 1764ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan progress = 1.0f; 1765ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1766ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1767ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float inFromXValue, inToXValue; 1768ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float outFromXValue, outToXValue; 1769ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (forward) { 1770ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inFromXValue = 1.0f - progress; 1771ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inToXValue = 0.0f; 1772ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outFromXValue = -progress; 1773ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outToXValue = -1.0f; 1774ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } else { 1775ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inFromXValue = progress - 1.0f; 1776ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inToXValue = 0.0f; 1777ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outFromXValue = progress; 1778ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outToXValue = 1.0f; 1779ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1780ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 17816d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan final Time start = new Time(mBaseDate.timezone); 17826d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan start.set(mController.getTime()); 17836d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (forward) { 17846d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan start.monthDay += mNumDays; 17856d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } else { 17866d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan start.monthDay -= mNumDays; 17876d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 1788f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mController.setTime(start.normalize(true)); 1789f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan 1790f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Time newSelected = start; 17916d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 17926d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (mNumDays == 7) { 1793f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan newSelected = new Time(start); 17946d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan adjustToBeginningOfWeek(start); 17956d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 17966d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 17976d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan final Time end = new Time(start); 17986d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan end.monthDay += mNumDays - 1; 17996d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 1800ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // We have to allocate these animation objects each time we switch views 1801ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // because that is the only way to set the animation parameters. 1802ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan TranslateAnimation inAnimation = new TranslateAnimation( 1803ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, inFromXValue, 1804ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, inToXValue, 1805ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f, 1806ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f); 1807ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1808ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan TranslateAnimation outAnimation = new TranslateAnimation( 1809ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, outFromXValue, 1810ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, outToXValue, 1811ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f, 1812ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f); 1813ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 18142c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan long duration = calculateDuration(width - Math.abs(xOffSet), width, velocity); 1815ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inAnimation.setDuration(duration); 18162c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan inAnimation.setInterpolator(mHScrollInterpolator); 18172c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan outAnimation.setInterpolator(mHScrollInterpolator); 1818ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outAnimation.setDuration(duration); 18196d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan outAnimation.setAnimationListener(new GotoBroadcaster(start, end)); 1820ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.setInAnimation(inAnimation); 1821ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.setOutAnimation(outAnimation); 1822ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1823d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getCurrentView(); 1824ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.cleanup(); 1825ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.showNext(); 1826d190418220467c02327dd9b3ae1eae238889720bMichael Chan view = (DayView) mViewSwitcher.getCurrentView(); 18275b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik view.setSelected(newSelected, true, false); 1828ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.requestFocus(); 1829ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.reloadEvents(); 1830eaafa2b48be7194a61754604ae37b3d62e9118d8Erik view.updateTitle(); 183158f5055e1f3740382b4507e6eb88eebc2d6c21c1Michael Chan view.restartCurrentTimeUpdates(); 1832e98dd73c67205b01f5348271d9a7a630003ecf52David Brown 1833ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return view; 1834ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1835ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1836146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is called after scrolling stops to move the selected hour 1837146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // to the visible part of the screen. 1838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void resetSelectedHour() { 1839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < mFirstHour + 1) { 1840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + 1; 1841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1842146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1843146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1844146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionHour > mFirstHour + mNumHours - 3) { 1845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + mNumHours - 3; 1846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1847146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1848146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1849146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1850146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1851146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1852146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void initFirstHour() { 1853d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mFirstHour = mSelectionHour - mNumHours / 5; 1854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 0) { 1855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = 0; 1856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mFirstHour + mNumHours > 24) { 1857146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = 24 - mNumHours; 1858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1860146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1861146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1862146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Recomputes the first full hour that is visible on screen after the 1863146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * screen is scrolled. 1864146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1865146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeFirstHour() { 1866146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the first full hour that is visible on screen 1867146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = (mViewStartY + mCellHeight + HOUR_GAP - 1) / (mCellHeight + HOUR_GAP); 1868146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = mFirstHour * (mCellHeight + HOUR_GAP) - mViewStartY; 1869146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1870146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1871146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void adjustHourSelection() { 1872146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < 0) { 1873146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = 0; 18742fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > 0) { 1875146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 18762fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = true; 1877146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1878146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1879146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1880146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour > 23) { 1881146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = 23; 1882146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1883146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1884146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the selected hour is at least 2 time slots from the top and 1885146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // bottom of the screen, then don't scroll the view. 1886146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < mFirstHour + 1) { 1887146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there are all-days events for the selected day but there 1888146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // are no more normal events earlier in the day, then jump to 1889146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the all-day event area. 1890146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Exception 1: allow the user to scroll to 8am with the trackball 1891146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // before jumping to the all-day event area. 1892146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Exception 2: if 12am is on screen, then allow the user to select 1893146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // 12am before going up to the all-day event area. 1894146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 18952fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > 0 && mEarliestStartHour[daynum] > mSelectionHour 1896146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && mFirstHour > 0 && mFirstHour < 8) { 1897146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 18982fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = true; 1899146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = mFirstHour + 1; 1900146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1901146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1902146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1903146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour > 0) { 1904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour -= 1; 1905146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY -= (mCellHeight + HOUR_GAP); 1906146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 1907146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 1908146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1909146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1910146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1911146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1912146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1913146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour > mFirstHour + mNumHours - 3) { 1914146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 24 - mNumHours) { 1915146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour += 1; 1916146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY += (mCellHeight + HOUR_GAP); 1917c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik if (mViewStartY > mMaxViewStartY) { 1918c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mViewStartY = mMaxViewStartY; 1919146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1920146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1921146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mFirstHour == 24 - mNumHours && mFirstHourOffset > 0) { 1922c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mViewStartY = mMaxViewStartY; 1923146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1924146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1925146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1926146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1927146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project void clearCachedEvents() { 1928146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastReloadMillis = 0; 1929146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Runnable mCancelCallback = new Runnable() { 1932146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 1933146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project clearCachedEvents(); 1934146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1935146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 1936146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 193746b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa /* package */ void reloadEvents() { 1938146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against this being called before this view has been 1939146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // initialized. 1940ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// if (mContext == null) { 1941ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// return; 1942ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// } 1943146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1944731f1cb808b7586b93615b408ab2636081fab0dcErik // Make sure our time zones are up to date 1945731f1cb808b7586b93615b408ab2636081fab0dcErik mTZUpdater.run(); 1946731f1cb808b7586b93615b408ab2636081fab0dcErik 1947146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 1948146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1949146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1951146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The start date is the beginning of the week at 12am 1952731f1cb808b7586b93615b408ab2636081fab0dcErik Time weekStart = new Time(Utils.getTimeZone(mContext, mTZUpdater)); 1953146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.set(mBaseDate); 1954146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.hour = 0; 1955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.minute = 0; 1956146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.second = 0; 1957146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = weekStart.normalize(true /* ignore isDst */); 1958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1959146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Avoid reloading events unnecessarily. 1960146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (millis == mLastReloadMillis) { 1961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastReloadMillis = millis; 1964146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // load events in the background 1966ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.startProgressSpinner(); 1967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final ArrayList<Event> events = new ArrayList<Event>(); 1968b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik mEventLoader.loadEventsInBackground(mNumDays, events, mFirstJulianDay, new Runnable() { 1969146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 1970146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEvents = events; 197108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mAllDayEvents == null) { 197208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents = new ArrayList<Event>(); 197308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 197408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents.clear(); 197508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 197608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 197708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Create a shorter array for all day events 197846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan for (Event e : events) { 197968655b5af2b7e5f872a103858ec58a19042123ceRoboErik if (e.drawAsAllday()) { 198008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents.add(e); 198108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 198208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 198308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 198408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // New events, new layouts 198508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mLayouts == null || mLayouts.length < events.size()) { 198608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mLayouts = new StaticLayout[events.size()]; 198708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 198808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Arrays.fill(mLayouts, null); 19893e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 199008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 199108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mAllDayLayouts == null || mAllDayLayouts.length < mAllDayEvents.size()) { 199208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayLayouts = new StaticLayout[events.size()]; 199308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 199408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Arrays.fill(mAllDayLayouts, null); 199508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 199608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 19972fda24534978f55711526dbde747aa50d68dec40RoboErik computeEventRelations(); 19982fda24534978f55711526dbde747aa50d68dec40RoboErik 1999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = true; 2000146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 2001146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 2002ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.stopProgressSpinner(); 2003146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 2004146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2005146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }, mCancelCallback); 2006146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2007146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20082fda24534978f55711526dbde747aa50d68dec40RoboErik private void computeEventRelations() { 20092fda24534978f55711526dbde747aa50d68dec40RoboErik // Compute the layout relation between each event before measuring cell 20102fda24534978f55711526dbde747aa50d68dec40RoboErik // width, as the cell width should be adjusted along with the relation. 20112fda24534978f55711526dbde747aa50d68dec40RoboErik // 20122fda24534978f55711526dbde747aa50d68dec40RoboErik // Examples: A (1:00pm - 1:01pm), B (1:02pm - 2:00pm) 20132fda24534978f55711526dbde747aa50d68dec40RoboErik // We should mark them as "overwapped". Though they are not overwapped logically, but 20142fda24534978f55711526dbde747aa50d68dec40RoboErik // minimum cell height implicitly expands the cell height of A and it should look like 20152fda24534978f55711526dbde747aa50d68dec40RoboErik // (1:00pm - 1:15pm) after the cell height adjustment. 20162fda24534978f55711526dbde747aa50d68dec40RoboErik 20172fda24534978f55711526dbde747aa50d68dec40RoboErik // Compute the space needed for the all-day events, if any. 20182fda24534978f55711526dbde747aa50d68dec40RoboErik // Make a pass over all the events, and keep track of the maximum 20192fda24534978f55711526dbde747aa50d68dec40RoboErik // number of all-day events in any one day. Also, keep track of 20202fda24534978f55711526dbde747aa50d68dec40RoboErik // the earliest event in each day. 20212fda24534978f55711526dbde747aa50d68dec40RoboErik int maxAllDayEvents = 0; 20222fda24534978f55711526dbde747aa50d68dec40RoboErik final ArrayList<Event> events = mEvents; 20232fda24534978f55711526dbde747aa50d68dec40RoboErik final int len = events.size(); 20242fda24534978f55711526dbde747aa50d68dec40RoboErik // Num of all-day-events on each day. 20252fda24534978f55711526dbde747aa50d68dec40RoboErik final int eventsCount[] = new int[mLastJulianDay - mFirstJulianDay + 1]; 20262fda24534978f55711526dbde747aa50d68dec40RoboErik Arrays.fill(eventsCount, 0); 20272fda24534978f55711526dbde747aa50d68dec40RoboErik for (int ii = 0; ii < len; ii++) { 20282fda24534978f55711526dbde747aa50d68dec40RoboErik Event event = events.get(ii); 20292fda24534978f55711526dbde747aa50d68dec40RoboErik if (event.startDay > mLastJulianDay || event.endDay < mFirstJulianDay) { 20302fda24534978f55711526dbde747aa50d68dec40RoboErik continue; 20312fda24534978f55711526dbde747aa50d68dec40RoboErik } 20322fda24534978f55711526dbde747aa50d68dec40RoboErik if (event.drawAsAllday()) { 20332fda24534978f55711526dbde747aa50d68dec40RoboErik // Count all the events being drawn as allDay events 20342fda24534978f55711526dbde747aa50d68dec40RoboErik final int firstDay = Math.max(event.startDay, mFirstJulianDay); 20352fda24534978f55711526dbde747aa50d68dec40RoboErik final int lastDay = Math.min(event.endDay, mLastJulianDay); 20362fda24534978f55711526dbde747aa50d68dec40RoboErik for (int day = firstDay; day <= lastDay; day++) { 20372fda24534978f55711526dbde747aa50d68dec40RoboErik final int count = ++eventsCount[day - mFirstJulianDay]; 20382fda24534978f55711526dbde747aa50d68dec40RoboErik if (maxAllDayEvents < count) { 20392fda24534978f55711526dbde747aa50d68dec40RoboErik maxAllDayEvents = count; 20402fda24534978f55711526dbde747aa50d68dec40RoboErik } 20412fda24534978f55711526dbde747aa50d68dec40RoboErik } 20422fda24534978f55711526dbde747aa50d68dec40RoboErik 20432fda24534978f55711526dbde747aa50d68dec40RoboErik int daynum = event.startDay - mFirstJulianDay; 20442fda24534978f55711526dbde747aa50d68dec40RoboErik int durationDays = event.endDay - event.startDay + 1; 20452fda24534978f55711526dbde747aa50d68dec40RoboErik if (daynum < 0) { 20462fda24534978f55711526dbde747aa50d68dec40RoboErik durationDays += daynum; 20472fda24534978f55711526dbde747aa50d68dec40RoboErik daynum = 0; 20482fda24534978f55711526dbde747aa50d68dec40RoboErik } 20492fda24534978f55711526dbde747aa50d68dec40RoboErik if (daynum + durationDays > mNumDays) { 20502fda24534978f55711526dbde747aa50d68dec40RoboErik durationDays = mNumDays - daynum; 20512fda24534978f55711526dbde747aa50d68dec40RoboErik } 20522fda24534978f55711526dbde747aa50d68dec40RoboErik for (int day = daynum; durationDays > 0; day++, durationDays--) { 20532fda24534978f55711526dbde747aa50d68dec40RoboErik mHasAllDayEvent[day] = true; 20542fda24534978f55711526dbde747aa50d68dec40RoboErik } 20552fda24534978f55711526dbde747aa50d68dec40RoboErik } else { 20562fda24534978f55711526dbde747aa50d68dec40RoboErik int daynum = event.startDay - mFirstJulianDay; 20572fda24534978f55711526dbde747aa50d68dec40RoboErik int hour = event.startTime / 60; 20582fda24534978f55711526dbde747aa50d68dec40RoboErik if (daynum >= 0 && hour < mEarliestStartHour[daynum]) { 20592fda24534978f55711526dbde747aa50d68dec40RoboErik mEarliestStartHour[daynum] = hour; 20602fda24534978f55711526dbde747aa50d68dec40RoboErik } 20612fda24534978f55711526dbde747aa50d68dec40RoboErik 20622fda24534978f55711526dbde747aa50d68dec40RoboErik // Also check the end hour in case the event spans more than 20632fda24534978f55711526dbde747aa50d68dec40RoboErik // one day. 20642fda24534978f55711526dbde747aa50d68dec40RoboErik daynum = event.endDay - mFirstJulianDay; 20652fda24534978f55711526dbde747aa50d68dec40RoboErik hour = event.endTime / 60; 20662fda24534978f55711526dbde747aa50d68dec40RoboErik if (daynum < mNumDays && hour < mEarliestStartHour[daynum]) { 20672fda24534978f55711526dbde747aa50d68dec40RoboErik mEarliestStartHour[daynum] = hour; 20682fda24534978f55711526dbde747aa50d68dec40RoboErik } 20692fda24534978f55711526dbde747aa50d68dec40RoboErik } 20702fda24534978f55711526dbde747aa50d68dec40RoboErik } 20712fda24534978f55711526dbde747aa50d68dec40RoboErik mMaxAlldayEvents = maxAllDayEvents; 20722fda24534978f55711526dbde747aa50d68dec40RoboErik initAllDayHeights(); 20732fda24534978f55711526dbde747aa50d68dec40RoboErik } 20742fda24534978f55711526dbde747aa50d68dec40RoboErik 2075146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 2076146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected void onDraw(Canvas canvas) { 2077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mRemeasure) { 2078146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project remeasure(getWidth(), getHeight()); 2079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = false; 2080146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2081c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.save(); 2082146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20832fda24534978f55711526dbde747aa50d68dec40RoboErik float yTranslate = -mViewStartY + DAY_HEADER_HEIGHT + mAlldayHeight; 2084c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // offset canvas by the current drag and header position 2085c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(-mViewStartX, yTranslate); 2086c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // clip to everything below the allDay area 2087c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik Rect dest = mDestRect; 2088c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.top = (int) (mFirstCell - yTranslate); 2089c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.bottom = (int) (mViewHeight - yTranslate); 2090c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.left = 0; 2091c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.right = mViewWidth; 2092c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.save(); 2093c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.clipRect(dest); 2094c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Draw the movable part of the view 2095c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik doDraw(canvas); 2096c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // restore to having no clip 2097c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.restore(); 2098146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 2100c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik float xTranslate; 2101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartX > 0) { 2102c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik xTranslate = mViewWidth; 2103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2104c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik xTranslate = -mViewWidth; 2105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2106c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Move the canvas around to prep it for the next view 2107c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // specifically, shift it by a screen and undo the 2108c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // yTranslation which will be redone in the nextView's onDraw(). 2109c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(xTranslate, -yTranslate); 2110d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView nextView = (DayView) mViewSwitcher.getNextView(); 2111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Prevent infinite recursive calls to onDraw(). 2113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project nextView.mTouchMode = TOUCH_MODE_INITIAL_STATE; 2114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project nextView.onDraw(canvas); 2116c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Move it back for this view 2117c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(-xTranslate, 0); 2118c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik } else { 2119c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // If we drew another view we already translated it back 2120c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // If we didn't draw another view we should be at the edge of the 2121c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // screen 2122c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(mViewStartX, -yTranslate); 2123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the fixed areas (that don't scroll) directly to the canvas. 2126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAfterScroll(canvas); 21278307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik if (mComputeSelectedEvents && mUpdateToast) { 21288307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik updateEventDetails(); 21298307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik mUpdateToast = false; 21308307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik } 2131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = false; 2132433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 2133433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // Draw overscroll glow 2134433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (!mEdgeEffectTop.isFinished()) { 2135433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (DAY_HEADER_HEIGHT != 0) { 2136433ba924de1ac26b923e2beb061812012749e4f3Michael Chan canvas.translate(0, DAY_HEADER_HEIGHT); 2137433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2138433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mEdgeEffectTop.draw(canvas)) { 2139433ba924de1ac26b923e2beb061812012749e4f3Michael Chan invalidate(); 2140433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2141433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (DAY_HEADER_HEIGHT != 0) { 2142433ba924de1ac26b923e2beb061812012749e4f3Michael Chan canvas.translate(0, -DAY_HEADER_HEIGHT); 2143433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2144433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2145433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (!mEdgeEffectBottom.isFinished()) { 2146433ba924de1ac26b923e2beb061812012749e4f3Michael Chan canvas.rotate(180, mViewWidth/2, mViewHeight/2); 2147433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mEdgeEffectBottom.draw(canvas)) { 2148433ba924de1ac26b923e2beb061812012749e4f3Michael Chan invalidate(); 2149433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2150433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.restore(); 2152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAfterScroll(Canvas canvas) { 2155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mPaint; 2156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r = mRect; 2157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2158e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik drawAllDayHighlights(r, canvas, p); 21592fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents != 0) { 21601ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan drawAllDayEvents(mFirstJulianDay, mNumDays, canvas, p); 21618f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan drawUpperLeftCorner(r, canvas, p); 2162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2164c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik drawScrollLine(r, canvas, p); 21653eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan drawDayHeaderLoop(r, canvas, p); 2166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the AM and PM indicators if we're in 12 hour mode 2168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!mIs24HourFormat) { 2169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAmPm(canvas, p); 2170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 217346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // This isn't really the upper-left corner. It's the square area just 2174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // below the upper-left corner, above the hours and to the left of the 2175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // all-day area. 21768f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private void drawUpperLeftCorner(Rect r, Canvas canvas, Paint p) { 21778f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan setupHourTextPaint(p); 21782fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount) { 2179cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik // Draw the allDay expand/collapse icon 2180cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik if (mUseExpandIcon) { 2181cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mExpandAlldayDrawable.setBounds(mExpandAllDayRect); 2182cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mExpandAlldayDrawable.draw(canvas); 2183cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik } else { 2184cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mCollapseAlldayDrawable.setBounds(mExpandAllDayRect); 2185cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mCollapseAlldayDrawable.draw(canvas); 2186cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik } 21872fda24534978f55711526dbde747aa50d68dec40RoboErik } 21888f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan } 2189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2190c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik private void drawScrollLine(Rect r, Canvas canvas, Paint p) { 2191b03348cec4c175846f074a656db5c121d5467e2dMichael Chan final int right = computeDayLeftPosition(mNumDays); 21928f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan final int y = mFirstCell - 1; 21938f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan 2194c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(false); 21958f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setStyle(Style.FILL); 21968f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan 21978f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setColor(mCalendarGridLineInnerHorizontalColor); 21988f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 21998f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawLine(GRID_LINE_LEFT_MARGIN, y, right, y, p); 2200c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(true); 2201c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik } 2202c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik 2203b03348cec4c175846f074a656db5c121d5467e2dMichael Chan // Computes the x position for the left side of the given day (base 0) 2204e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private int computeDayLeftPosition(int day) { 2205e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int effectiveWidth = mViewWidth - mHoursWidth; 2206e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik return day * effectiveWidth / mNumDays + mHoursWidth; 2207e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2208e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 2209e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private void drawAllDayHighlights(Rect r, Canvas canvas, Paint p) { 2210cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan if (mFutureBgColor != 0) { 2211cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan // First, color the labels area light gray 2212e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.top = 0; 2213cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.bottom = DAY_HEADER_HEIGHT; 2214cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.left = 0; 2215cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.right = mViewWidth; 2216cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan p.setColor(mBgColor); 2217e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setStyle(Style.FILL); 2218e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik canvas.drawRect(r, p); 2219cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan // and the area that says All day 2220cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.top = DAY_HEADER_HEIGHT; 2221cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.bottom = mFirstCell - 1; 2222cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.left = 0; 2223cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.right = mHoursWidth; 2224cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan canvas.drawRect(r, p); 2225cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan 2226cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan int startIndex = -1; 2227cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan 2228cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan int todayIndex = mTodayJulianDay - mFirstJulianDay; 2229cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan if (todayIndex < 0) { 2230cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan // Future 2231cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan startIndex = 0; 2232cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } else if (todayIndex >= 1 && todayIndex + 1 < mNumDays) { 2233cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan // Multiday - tomorrow is visible. 2234cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan startIndex = todayIndex + 1; 2235cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } 2236cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan 2237cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan if (startIndex >= 0) { 2238cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan // Draw the future highlight 2239cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.top = 0; 2240cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.bottom = mFirstCell - 1; 2241cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.left = computeDayLeftPosition(startIndex) + 1; 2242b03348cec4c175846f074a656db5c121d5467e2dMichael Chan r.right = computeDayLeftPosition(mNumDays); 2243cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan p.setColor(mFutureBgColor); 2244cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan p.setStyle(Style.FILL); 2245cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan canvas.drawRect(r, p); 2246cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } 2247e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 224821bd42039c92232647f54461cd20708224cc7eb6Michael Chan 2249b6fb51224b578b26e503fddae2799d03a2aaad47RoboErik if (mSelectionAllday && mSelectionMode != SELECTION_HIDDEN) { 2250e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik // Draw the selection highlight on the selected all-day area 2251e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mRect.top = DAY_HEADER_HEIGHT + 1; 2252e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mRect.bottom = mRect.top + mAlldayHeight + ALLDAY_TOP_MARGIN - 2; 2253e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int daynum = mSelectionDay - mFirstJulianDay; 2254e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mRect.left = computeDayLeftPosition(daynum) + 1; 2255e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mRect.right = computeDayLeftPosition(daynum + 1); 2256e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setColor(mCalendarGridAreaSelected); 2257e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik canvas.drawRect(mRect, p); 2258e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2259e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2260e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 2261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawDayHeaderLoop(Rect r, Canvas canvas, Paint p) { 2262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the horizontal day background banner 22633eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarDateBannerBackground); 22643eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = 0; 22653eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = DAY_HEADER_HEIGHT; 22663eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = 0; 22673eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mHoursWidth + mNumDays * (mCellWidth + DAY_GAP); 22683eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 22693eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // 2270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the extra space on the right side with the default background 22713eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = r.right; 22723eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mViewWidth; 22733eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 22743eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 2275e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik if (mNumDays == 1 && ONE_DAY_HEADER_HEIGHT == 0) { 2276e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik return; 2277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 22793eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTypeface(mBold); 22803eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextAlign(Paint.Align.RIGHT); 2281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cell = mFirstJulianDay; 2282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] dayNames; 2284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mDateStrWidth < mCellWidth) { 2285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dayNames = mDayStrs; 2286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dayNames = mDayStrs2Letter; 2288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2290d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setAntiAlias(true); 2291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++, cell++) { 22921f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan int dayOfWeek = day + mFirstVisibleDayOfWeek; 22931f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan if (dayOfWeek >= 14) { 22941f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan dayOfWeek -= 14; 2295487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 2296487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 22973eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int color = mCalendarDateBannerTextColor; 2298071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (mNumDays == 1) { 2299071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (dayOfWeek == Time.SATURDAY) { 2300071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_saturdayColor; 2301071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else if (dayOfWeek == Time.SUNDAY) { 2302071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_sundayColor; 2303071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } 2304071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else { 2305071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa final int column = day % 7; 2306071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (Utils.isSaturday(column, mFirstDayOfWeek)) { 2307071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_saturdayColor; 2308071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else if (Utils.isSunday(column, mFirstDayOfWeek)) { 2309071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_sundayColor; 2310071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } 23113eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 23123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 23133eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(color); 2314e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik drawDayHeader(dayNames[dayOfWeek], day, cell, canvas, p); 2315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 23163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTypeface(null); 2317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAmPm(Canvas canvas, Paint p) { 2320d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarAmPmLabel); 2321e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextSize(AMPM_TEXT_SIZE); 2322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 2323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 2324e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextAlign(Paint.Align.RIGHT); 2325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String text = mAmString; 2326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour >= 12) { 2327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = mPmString; 2328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = mFirstCell + mFirstHourOffset + 2 * mHoursTextHeight + HOUR_GAP; 23308f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawText(text, HOURS_LEFT_MARGIN, y, p); 2331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 12 && mFirstHour + mNumHours > 12) { 2333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also draw the "PM" 2334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = mPmString; 2335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y = mFirstCell + mFirstHourOffset + (12 - mFirstHour) * (mCellHeight + HOUR_GAP) 2336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project + 2 * mHoursTextHeight + HOUR_GAP; 23378f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawText(text, HOURS_LEFT_MARGIN, y, p); 2338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2341e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private void drawCurrentTimeLine(Rect r, final int day, final int top, Canvas canvas, 2342f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan Paint p) { 2343e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.left = computeDayLeftPosition(day) - CURRENT_TIME_LINE_SIDE_BUFFER + 1; 2344763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.right = computeDayLeftPosition(day + 1) + CURRENT_TIME_LINE_SIDE_BUFFER + 1; 23453eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 2346763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.top = top - CURRENT_TIME_LINE_TOP_OFFSET; 23473eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.bottom = r.top + mCurrentTimeLine.getIntrinsicHeight(); 2348bd0e834aea317236d574f8738fe11a51fdc87968Erik 23493eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine.setBounds(r); 23503eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine.draw(canvas); 23515b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mAnimateToday) { 23525b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mCurrentTimeAnimateLine.setBounds(r); 23535b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mCurrentTimeAnimateLine.setAlpha(mAnimateTodayAlpha); 23545b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mCurrentTimeAnimateLine.draw(canvas); 23555b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2356bd0e834aea317236d574f8738fe11a51fdc87968Erik } 2357bd0e834aea317236d574f8738fe11a51fdc87968Erik 2358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void doDraw(Canvas canvas) { 2359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mPaint; 2360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r = mRect; 2361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2362cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan if (mFutureBgColor != 0) { 2363cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan drawBgColors(r, canvas, p); 2364cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } 2365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawGridBackground(r, canvas, p); 2366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawHours(r, canvas, p); 2367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw each day 2369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cell = mFirstJulianDay; 2370e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 2371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++, cell++) { 237208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // TODO Wow, this needs cleanup. drawEvents loop through all the 237308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // events on every call. 2374e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik drawEvents(cell, day, HOUR_GAP, canvas, p); 237546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // If this is today 237646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (cell == mTodayJulianDay) { 23771ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int lineY = mCurrentTime.hour * (mCellHeight + HOUR_GAP) 23781ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan + ((mCurrentTime.minute * mCellHeight) / 60) + 1; 23791ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 238046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // And the current time shows up somewhere on the screen 238146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (lineY >= mViewStartY && lineY < mViewStartY + mViewHeight - 2) { 2382e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik drawCurrentTimeLine(r, day, lineY, canvas, p); 2383bd0e834aea317236d574f8738fe11a51fdc87968Erik } 2384bd0e834aea317236d574f8738fe11a51fdc87968Erik } 2385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2386e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(true); 2387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 238895f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan drawSelectedRect(r, canvas, p); 238995f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan } 23903eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 239195f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan private void drawSelectedRect(Rect r, Canvas canvas, Paint p) { 2392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw a highlight on the selected hour (if needed) 23932fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSelectionMode != SELECTION_HIDDEN && !mSelectionAllday) { 23943937a47bc5a1afb9701e1d0565fae31f5800590dErik int daynum = mSelectionDay - mFirstJulianDay; 2395ba902466b19b11d587468e354edc58e542707747Michael Chan r.top = mSelectionHour * (mCellHeight + HOUR_GAP); 23961ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top + mCellHeight + HOUR_GAP; 2397d0c06c6c8815d027c595cb70b01478634a84c8e0RoboErik r.left = computeDayLeftPosition(daynum) + 1; 2398d0c06c6c8815d027c595cb70b01478634a84c8e0RoboErik r.right = computeDayLeftPosition(daynum + 1) + 1; 2399ba902466b19b11d587468e354edc58e542707747Michael Chan 2400ba902466b19b11d587468e354edc58e542707747Michael Chan saveSelectionPosition(r.left, r.top, r.right, r.bottom); 24013937a47bc5a1afb9701e1d0565fae31f5800590dErik 240295f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan // Draw the highlight on the grid 24033937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setColor(mCalendarGridAreaSelected); 24043937a47bc5a1afb9701e1d0565fae31f5800590dErik r.top += HOUR_GAP; 24053937a47bc5a1afb9701e1d0565fae31f5800590dErik r.right -= DAY_GAP; 2406e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 24073937a47bc5a1afb9701e1d0565fae31f5800590dErik canvas.drawRect(r, p); 240895f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan 2409ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson // Draw a "new event hint" on top of the highlight 2410ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson // For the week view, show a "+", for day view, show "+ New event" 2411ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setColor(mNewEventHintColor); 2412ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson if (mNumDays > 1) { 2413ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setStrokeWidth(NEW_EVENT_WIDTH); 2414ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int width = r.right - r.left; 2415ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int midX = r.left + width / 2; 2416ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int midY = r.top + mCellHeight / 2; 2417ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int length = Math.min(mCellHeight, width) - NEW_EVENT_MARGIN * 2; 2418ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson length = Math.min(length, NEW_EVENT_MAX_LENGTH); 2419ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int verticalPadding = (mCellHeight - length) / 2; 2420ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int horizontalPadding = (width - length) / 2; 2421ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson canvas.drawLine(r.left + horizontalPadding, midY, r.right - horizontalPadding, 2422ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson midY, p); 2423ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson canvas.drawLine(midX, r.top + verticalPadding, midX, r.bottom - verticalPadding, p); 2424ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson } else { 2425ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setStyle(Paint.Style.FILL); 2426ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setTextSize(NEW_EVENT_HINT_FONT_SIZE); 2427ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setTextAlign(Paint.Align.LEFT); 2428ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); 2429ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson canvas.drawText(mNewEventHintString, r.left + EVENT_TEXT_LEFT_MARGIN, 2430ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson r.top + Math.abs(p.getFontMetrics().ascent) + EVENT_TEXT_TOP_MARGIN , p); 2431ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson } 2432ba902466b19b11d587468e354edc58e542707747Michael Chan } 243395f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan } 2434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 243595f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan private void drawHours(Rect r, Canvas canvas, Paint p) { 24368f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan setupHourTextPaint(p); 2437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 24388f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan int y = HOUR_GAP + mHoursTextHeight + HOURS_TOP_MARGIN; 2439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < 24; i++) { 2441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String time = mHourStrs[i]; 24428f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawText(time, HOURS_LEFT_MARGIN, y, p); 2443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += mCellHeight + HOUR_GAP; 2444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 24478f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private void setupHourTextPaint(Paint p) { 24488f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setColor(mCalendarHourLabelColor); 2449e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextSize(HOURS_TEXT_SIZE); 2450f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(Typeface.DEFAULT); 2451e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextAlign(Paint.Align.RIGHT); 24528f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setAntiAlias(true); 24538f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan } 24548f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan 2455e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private void drawDayHeader(String dayStr, int day, int cell, Canvas canvas, Paint p) { 2456487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int dateNum = mFirstVisibleDate + day; 2457e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int x; 2458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (dateNum > mMonthLength) { 2459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dateNum -= mMonthLength; 2460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2461e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(true); 2462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2463763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik int todayIndex = mTodayJulianDay - mFirstJulianDay; 24643eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 24653eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan String dateNumStr = String.valueOf(dateNum); 24663eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mNumDays > 1) { 24673eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float y = DAY_HEADER_HEIGHT - DAY_HEADER_BOTTOM_MARGIN; 24683eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 24693eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 2470e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik x = computeDayLeftPosition(day + 1) - DAY_HEADER_RIGHT_MARGIN; 2471e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextAlign(Align.RIGHT); 24723eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 2473763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik 2474763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik p.setTypeface(todayIndex == day ? mBold : Typeface.DEFAULT); 24753eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dateNumStr, x, y, p); 24763eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 24773eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the week 2478e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik x -= p.measureText(" " + dateNumStr); 24793eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 2480f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(Typeface.DEFAULT); 24813eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dayStr, x, y, p); 2482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2483e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik float y = ONE_DAY_HEADER_HEIGHT - DAY_HEADER_ONE_DAY_BOTTOM_MARGIN; 2484e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextAlign(Align.LEFT); 2485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2486f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan 24873eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the week 2488e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik x = computeDayLeftPosition(day) + DAY_HEADER_ONE_DAY_LEFT_MARGIN; 24893eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 2490f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(Typeface.DEFAULT); 24913eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dayStr, x, y, p); 2492d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan 24933eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 24943eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += p.measureText(dayStr) + DAY_HEADER_ONE_DAY_RIGHT_MARGIN; 24953eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 2496763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik p.setTypeface(todayIndex == day ? mBold : Typeface.DEFAULT); 24973eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dateNumStr, x, y, p); 2498d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan } 2499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2501146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawGridBackground(Rect r, Canvas canvas, Paint p) { 2502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint.Style savedStyle = p.getStyle(); 2503146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2504b03348cec4c175846f074a656db5c121d5467e2dMichael Chan final float stopX = computeDayLeftPosition(mNumDays); 2505000ba1109e2f4e527e9227fe341598ceeb3fbca6Michael Chan float y = 0; 25063eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaY = mCellHeight + HOUR_GAP; 250702041687c35441e8a21cb763f1fc3a26525292efDavid Brown int linesIndex = 0; 25083eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startY = 0; 25093eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP); 25101ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan float x = mHoursWidth; 2511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 25123eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner horizontal grid lines 25133eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerHorizontalColor); 25143eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 2515e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 25163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan y = 0; 251702041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 25183eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int hour = 0; hour <= 24; hour++) { 25198f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mLines[linesIndex++] = GRID_LINE_LEFT_MARGIN; 252002041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 252102041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopX; 252202041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 25233eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan y += deltaY; 25243eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 252502041687c35441e8a21cb763f1fc3a26525292efDavid Brown if (mCalendarGridLineInnerVerticalColor != mCalendarGridLineInnerHorizontalColor) { 252602041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 252702041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 252802041687c35441e8a21cb763f1fc3a26525292efDavid Brown p.setColor(mCalendarGridLineInnerVerticalColor); 252902041687c35441e8a21cb763f1fc3a26525292efDavid Brown } 25303eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 25313eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner vertical grid lines 2532e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik for (int day = 0; day <= mNumDays; day++) { 2533e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik x = computeDayLeftPosition(day); 253402041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 253502041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 253602041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 253702041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 25383eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 253902041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 25403eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 2541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Restore the saved style. 2542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setStyle(savedStyle); 2543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 2544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2546e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik /** 2547e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * @param r 2548e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * @param canvas 2549e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * @param p 2550e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik */ 2551e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private void drawBgColors(Rect r, Canvas canvas, Paint p) { 2552e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int todayIndex = mTodayJulianDay - mFirstJulianDay; 2553e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik // Draw the hours background color 2554e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.top = mDestRect.top; 2555e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.bottom = mDestRect.bottom; 2556e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.left = 0; 2557e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.right = mHoursWidth; 2558e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setColor(mBgColor); 2559e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setStyle(Style.FILL); 2560e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 2561e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik canvas.drawRect(r, p); 256221bd42039c92232647f54461cd20708224cc7eb6Michael Chan 256321bd42039c92232647f54461cd20708224cc7eb6Michael Chan // Draw background for grid area 2564e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik if (mNumDays == 1 && todayIndex == 0) { 2565e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik // Draw a white background for the time later than current time 2566e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int lineY = mCurrentTime.hour * (mCellHeight + HOUR_GAP) 2567e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik + ((mCurrentTime.minute * mCellHeight) / 60) + 1; 2568e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik if (lineY < mViewStartY + mViewHeight) { 2569e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik lineY = Math.max(lineY, mViewStartY); 2570e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.left = mHoursWidth; 2571e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.right = mViewWidth; 2572e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.top = lineY; 2573e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.bottom = mViewStartY + mViewHeight; 257421bd42039c92232647f54461cd20708224cc7eb6Michael Chan p.setColor(mFutureBgColor); 2575e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik canvas.drawRect(r, p); 2576e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2577e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } else if (todayIndex >= 0 && todayIndex < mNumDays) { 257821bd42039c92232647f54461cd20708224cc7eb6Michael Chan // Draw today with a white background for the time later than current time 257921bd42039c92232647f54461cd20708224cc7eb6Michael Chan int lineY = mCurrentTime.hour * (mCellHeight + HOUR_GAP) 258021bd42039c92232647f54461cd20708224cc7eb6Michael Chan + ((mCurrentTime.minute * mCellHeight) / 60) + 1; 258121bd42039c92232647f54461cd20708224cc7eb6Michael Chan if (lineY < mViewStartY + mViewHeight) { 258221bd42039c92232647f54461cd20708224cc7eb6Michael Chan lineY = Math.max(lineY, mViewStartY); 258321bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.left = computeDayLeftPosition(todayIndex) + 1; 258421bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.right = computeDayLeftPosition(todayIndex + 1); 258521bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.top = lineY; 258621bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.bottom = mViewStartY + mViewHeight; 258721bd42039c92232647f54461cd20708224cc7eb6Michael Chan p.setColor(mFutureBgColor); 258821bd42039c92232647f54461cd20708224cc7eb6Michael Chan canvas.drawRect(r, p); 258921bd42039c92232647f54461cd20708224cc7eb6Michael Chan } 259021bd42039c92232647f54461cd20708224cc7eb6Michael Chan 259121bd42039c92232647f54461cd20708224cc7eb6Michael Chan // Paint Tomorrow and later days with future color 259221bd42039c92232647f54461cd20708224cc7eb6Michael Chan if (todayIndex + 1 < mNumDays) { 259321bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.left = computeDayLeftPosition(todayIndex + 1) + 1; 2594b03348cec4c175846f074a656db5c121d5467e2dMichael Chan r.right = computeDayLeftPosition(mNumDays); 259521bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.top = mDestRect.top; 259621bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.bottom = mDestRect.bottom; 259721bd42039c92232647f54461cd20708224cc7eb6Michael Chan p.setColor(mFutureBgColor); 259821bd42039c92232647f54461cd20708224cc7eb6Michael Chan canvas.drawRect(r, p); 259921bd42039c92232647f54461cd20708224cc7eb6Michael Chan } 260021bd42039c92232647f54461cd20708224cc7eb6Michael Chan } else if (todayIndex < 0) { 260121bd42039c92232647f54461cd20708224cc7eb6Michael Chan // Future 260221bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.left = computeDayLeftPosition(0) + 1; 2603b03348cec4c175846f074a656db5c121d5467e2dMichael Chan r.right = computeDayLeftPosition(mNumDays); 2604e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.top = mDestRect.top; 2605e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.bottom = mDestRect.bottom; 260621bd42039c92232647f54461cd20708224cc7eb6Michael Chan p.setColor(mFutureBgColor); 2607e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik canvas.drawRect(r, p); 2608e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2609e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(true); 2610e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2611e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 2612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event getSelectedEvent() { 2613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 2614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // There is no event at the selected hour, so create a new event. 2615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return getNewEvent(mSelectionDay, getSelectedTimeInMillis(), 2616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getSelectedMinutesSinceMidnight()); 2617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return mSelectedEvent; 2619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean isEventSelected() { 2622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return (mSelectedEvent != null); 2623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event getNewEvent() { 2626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return getNewEvent(mSelectionDay, getSelectedTimeInMillis(), 2627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getSelectedMinutesSinceMidnight()); 2628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project static Event getNewEvent(int julianDay, long utcMillis, 2631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int minutesSinceMidnight) { 2632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = Event.newInstance(); 2633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startDay = julianDay; 2634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endDay = julianDay; 2635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startMillis = utcMillis; 2636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endMillis = event.startMillis + MILLIS_PER_HOUR; 2637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startTime = minutesSinceMidnight; 2638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endTime = event.startTime + MINUTES_PER_HOUR; 2639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return event; 2640146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int computeMaxStringWidth(int currentMax, String[] strings, Paint p) { 2643146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float maxWidthF = 0.0f; 2644146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2645146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = strings.length; 2646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < len; i++) { 2647146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float width = p.measureText(strings[i]); 2648146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxWidthF = Math.max(width, maxWidthF); 2649146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2650146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxWidth = (int) (maxWidthF + 0.5); 2651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxWidth < currentMax) { 2652146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxWidth = currentMax; 2653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2654146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return maxWidth; 2655146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void saveSelectionPosition(float left, float top, float right, float bottom) { 2658146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.left = (int) left; 2659146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.right = (int) right; 2660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.top = (int) top; 2661146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.bottom = (int) bottom; 2662146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect getCurrentSelectionPosition() { 2665146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect box = new Rect(); 2666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.top = mSelectionHour * (mCellHeight + HOUR_GAP); 2667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.bottom = box.top + mCellHeight + HOUR_GAP; 2668146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 2669e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik box.left = computeDayLeftPosition(daynum) + 1; 2670e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik box.right = computeDayLeftPosition(daynum + 1); 2671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return box; 2672146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 26741ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void setupTextRect(Rect r) { 26751ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom <= r.top || r.right <= r.left) { 26761ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top; 26771ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = r.left; 267836a4668f603c432d08ad156cd7c731f9838c0212Michael Chan return; 267936a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 268036a4668f603c432d08ad156cd7c731f9838c0212Michael Chan 26811ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom - r.top > EVENT_TEXT_TOP_MARGIN + EVENT_TEXT_BOTTOM_MARGIN) { 26821ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top += EVENT_TEXT_TOP_MARGIN; 26831ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom -= EVENT_TEXT_BOTTOM_MARGIN; 268436a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 26851ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.right - r.left > EVENT_TEXT_LEFT_MARGIN + EVENT_TEXT_RIGHT_MARGIN) { 26861ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left += EVENT_TEXT_LEFT_MARGIN; 26871ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right -= EVENT_TEXT_RIGHT_MARGIN; 268836a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 26899c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan } 26909c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan 26911ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void setupAllDayTextRect(Rect r) { 26921ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom <= r.top || r.right <= r.left) { 26931ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top; 26941ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = r.left; 269536a4668f603c432d08ad156cd7c731f9838c0212Michael Chan return; 269636a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 269736a4668f603c432d08ad156cd7c731f9838c0212Michael Chan 26981ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom - r.top > EVENT_ALL_DAY_TEXT_TOP_MARGIN + EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN) { 26991ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top += EVENT_ALL_DAY_TEXT_TOP_MARGIN; 27001ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom -= EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN; 270136a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 27021ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.right - r.left > EVENT_ALL_DAY_TEXT_LEFT_MARGIN + EVENT_ALL_DAY_TEXT_RIGHT_MARGIN) { 27031ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left += EVENT_ALL_DAY_TEXT_LEFT_MARGIN; 27041ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right -= EVENT_ALL_DAY_TEXT_RIGHT_MARGIN; 270536a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 27069c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan } 27079c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan 27083e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh /** 27093e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh * Return the layout for a numbered event. Create it if not already existing 27103e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh */ 271108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout getEventLayout(StaticLayout[] layouts, int i, Event event, Paint paint, 271208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Rect r) { 271308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (i < 0 || i >= layouts.length) { 27140a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan return null; 27150a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan } 27160a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan 271708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = layouts[i]; 2718f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan // Check if we have already initialized the StaticLayout and that 2719f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan // the width hasn't changed (due to vertical resizing which causes 2720f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan // re-layout of events at min height) 27211ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (layout == null || r.width() != layout.getWidth()) { 2722e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik SpannableStringBuilder bob = new SpannableStringBuilder(); 2723e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik if (event.title != null) { 27241c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik // MAX - 1 since we add a space 27251c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik bob.append(drawTextSanitizer(event.title.toString(), MAX_EVENT_TEXT_LEN - 1)); 2726e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik bob.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, bob.length(), 0); 2727e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik bob.append(' '); 2728e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2729e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik if (event.location != null) { 2730e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik bob.append(drawTextSanitizer(event.location.toString(), 2731e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik MAX_EVENT_TEXT_LEN - bob.length())); 2732e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 27333e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 273425996100d6ea61888ebe54d7708a9a371bb12a55RoboErik switch (event.selfAttendeeStatus) { 273525996100d6ea61888ebe54d7708a9a371bb12a55RoboErik case Attendees.ATTENDEE_STATUS_INVITED: 273625996100d6ea61888ebe54d7708a9a371bb12a55RoboErik paint.setColor(event.color); 273725996100d6ea61888ebe54d7708a9a371bb12a55RoboErik break; 273825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik case Attendees.ATTENDEE_STATUS_DECLINED: 2739e6109c584d27a6c25df1819a5c6ec444e789ce61Isaac Katzenelson paint.setColor(mEventTextColor); 27404ecf0648e68bc9339a3d64745008a4617f7beddaIsaac Katzenelson paint.setAlpha(Utils.DECLINED_EVENT_TEXT_ALPHA); 2741e6109c584d27a6c25df1819a5c6ec444e789ce61Isaac Katzenelson break; 274225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik case Attendees.ATTENDEE_STATUS_NONE: // Your own events 274325996100d6ea61888ebe54d7708a9a371bb12a55RoboErik case Attendees.ATTENDEE_STATUS_ACCEPTED: 274425996100d6ea61888ebe54d7708a9a371bb12a55RoboErik case Attendees.ATTENDEE_STATUS_TENTATIVE: 274525996100d6ea61888ebe54d7708a9a371bb12a55RoboErik default: 274625996100d6ea61888ebe54d7708a9a371bb12a55RoboErik paint.setColor(mEventTextColor); 274725996100d6ea61888ebe54d7708a9a371bb12a55RoboErik break; 2748f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan } 2749f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan 27503e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh // Leave a one pixel boundary on the left and right of the rectangle for the event 2751e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik layout = new StaticLayout(bob, 0, bob.length(), new TextPaint(paint), r.width(), 27521ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true, null, r.width()); 27533e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 275408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan layouts[i] = layout; 27553e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 27563e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 27573e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh return layout; 27583e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 27593e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 27601ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void drawAllDayEvents(int firstDay, int numDays, Canvas canvas, Paint p) { 27613e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 2762146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(NORMAL_FONT_SIZE); 2763146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextAlign(Paint.Align.LEFT); 2764146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint eventTextPaint = mEventTextPaint; 2765146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 27663eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startY = DAY_HEADER_HEIGHT; 27672fda24534978f55711526dbde747aa50d68dec40RoboErik final float stopY = startY + mAlldayHeight + ALLDAY_TOP_MARGIN; 2768e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik float x = 0; 276902041687c35441e8a21cb763f1fc3a26525292efDavid Brown int linesIndex = 0; 27703eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 27713eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner vertical grid lines 27723eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerVerticalColor); 27731ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x = mHoursWidth; 27743eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 27751ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // Line bounding the top of the all day area 27768f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mLines[linesIndex++] = GRID_LINE_LEFT_MARGIN; 27771ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 2778b03348cec4c175846f074a656db5c121d5467e2dMichael Chan mLines[linesIndex++] = computeDayLeftPosition(mNumDays); 27791ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 27801ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 2781e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik for (int day = 0; day <= mNumDays; day++) { 2782e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik x = computeDayLeftPosition(day); 278302041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 278402041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 278502041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 278602041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 27873eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 2788e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 278902041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 2790146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setStyle(Style.FILL); 2791146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 27923eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int y = DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 2793146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int lastDay = firstDay + numDays - 1; 279408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final ArrayList<Event> events = mAllDayEvents; 2795146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 27962fda24534978f55711526dbde747aa50d68dec40RoboErik // Whether or not we should draw the more events text 27972fda24534978f55711526dbde747aa50d68dec40RoboErik boolean hasMoreEvents = false; 27982fda24534978f55711526dbde747aa50d68dec40RoboErik // size of the allDay area 27992fda24534978f55711526dbde747aa50d68dec40RoboErik float drawHeight = mAlldayHeight; 28002fda24534978f55711526dbde747aa50d68dec40RoboErik // max number of events being drawn in one day of the allday area 28012fda24534978f55711526dbde747aa50d68dec40RoboErik float numRectangles = mMaxAlldayEvents; 28022fda24534978f55711526dbde747aa50d68dec40RoboErik // Where to cut off drawn allday events 28032fda24534978f55711526dbde747aa50d68dec40RoboErik int allDayEventClip = DAY_HEADER_HEIGHT + mAlldayHeight + ALLDAY_TOP_MARGIN; 28042fda24534978f55711526dbde747aa50d68dec40RoboErik // The number of events that weren't drawn in each day 28052fda24534978f55711526dbde747aa50d68dec40RoboErik mSkippedAlldayEvents = new int[numDays]; 28062fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount && !mShowAllAllDayEvents && 28072fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayHeight == 0) { 28082fda24534978f55711526dbde747aa50d68dec40RoboErik // We draw one fewer event than will fit so that more events text 28092fda24534978f55711526dbde747aa50d68dec40RoboErik // can be drawn 28102fda24534978f55711526dbde747aa50d68dec40RoboErik numRectangles = mMaxUnexpandedAlldayEventCount - 1; 28112fda24534978f55711526dbde747aa50d68dec40RoboErik // We also clip the events above the more events text 28122fda24534978f55711526dbde747aa50d68dec40RoboErik allDayEventClip -= MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT; 28132fda24534978f55711526dbde747aa50d68dec40RoboErik hasMoreEvents = true; 28142fda24534978f55711526dbde747aa50d68dec40RoboErik } else if (mAnimateDayHeight != 0) { 28152fda24534978f55711526dbde747aa50d68dec40RoboErik // clip at the end of the animating space 28162fda24534978f55711526dbde747aa50d68dec40RoboErik allDayEventClip = DAY_HEADER_HEIGHT + mAnimateDayHeight + ALLDAY_TOP_MARGIN; 28172fda24534978f55711526dbde747aa50d68dec40RoboErik } 2818146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 2819146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 2820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startDay = event.startDay; 2821146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endDay = event.endDay; 2822c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (startDay > lastDay || endDay < firstDay) { 2823146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2824c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2825c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (startDay < firstDay) { 2826146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startDay = firstDay; 2827c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2828c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (endDay > lastDay) { 2829146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endDay = lastDay; 2830c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2831146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startIndex = startDay - firstDay; 2832146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endIndex = endDay - firstDay; 28332fda24534978f55711526dbde747aa50d68dec40RoboErik float height = mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount ? mAnimateDayEventHeight : 28342fda24534978f55711526dbde747aa50d68dec40RoboErik drawHeight / numRectangles; 2835146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2836146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Prevent a single event from getting too big 2837f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan if (height > MAX_HEIGHT_OF_ONE_ALLDAY_EVENT) { 2838f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan height = MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 2839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Leave a one-pixel space between the vertical day lines and the 2842146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event rectangle. 2843e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik event.left = computeDayLeftPosition(startIndex); 2844e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik event.right = computeDayLeftPosition(endIndex + 1) - DAY_GAP; 2845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.top = y + height * event.getColumn(); 284625996100d6ea61888ebe54d7708a9a371bb12a55RoboErik event.bottom = event.top + height - ALL_DAY_EVENT_RECT_BOTTOM_MARGIN; 28472fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount) { 28482fda24534978f55711526dbde747aa50d68dec40RoboErik // check if we should skip this event. We skip if it starts 28492fda24534978f55711526dbde747aa50d68dec40RoboErik // after the clip bound or ends after the skip bound and we're 28502fda24534978f55711526dbde747aa50d68dec40RoboErik // not animating. 28512fda24534978f55711526dbde747aa50d68dec40RoboErik if (event.top >= allDayEventClip) { 28522fda24534978f55711526dbde747aa50d68dec40RoboErik incrementSkipCount(mSkippedAlldayEvents, startIndex, endIndex); 28532fda24534978f55711526dbde747aa50d68dec40RoboErik continue; 28542fda24534978f55711526dbde747aa50d68dec40RoboErik } else if (event.bottom > allDayEventClip) { 28552fda24534978f55711526dbde747aa50d68dec40RoboErik if (hasMoreEvents) { 28562fda24534978f55711526dbde747aa50d68dec40RoboErik incrementSkipCount(mSkippedAlldayEvents, startIndex, endIndex); 28572fda24534978f55711526dbde747aa50d68dec40RoboErik continue; 28582fda24534978f55711526dbde747aa50d68dec40RoboErik } 28592fda24534978f55711526dbde747aa50d68dec40RoboErik event.bottom = allDayEventClip; 28602fda24534978f55711526dbde747aa50d68dec40RoboErik } 28612fda24534978f55711526dbde747aa50d68dec40RoboErik } 286225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik Rect r = drawEventRect(event, canvas, p, eventTextPaint, (int) event.top, 286325996100d6ea61888ebe54d7708a9a371bb12a55RoboErik (int) event.bottom); 28641ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan setupAllDayTextRect(r); 286508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = getEventLayout(mAllDayLayouts, i, event, eventTextPaint, r); 286608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan drawEventText(layout, r, canvas, r.top, r.bottom); 2867146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2868146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check if this all-day event intersects the selected day 28692fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSelectionAllday && mComputeSelectedEvents) { 2870146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (startDay <= mSelectionDay && endDay >= mSelectionDay) { 2871146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 2872146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2873146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2874146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 28752fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMoreAlldayEventsTextAlpha != 0 && mSkippedAlldayEvents != null) { 28762fda24534978f55711526dbde747aa50d68dec40RoboErik // If the more allday text should be visible, draw it. 28772fda24534978f55711526dbde747aa50d68dec40RoboErik p.setColor(mMoreAlldayEventsTextAlpha << 24 & mMoreEventsTextColor); 28782fda24534978f55711526dbde747aa50d68dec40RoboErik for (int i = 0; i < mSkippedAlldayEvents.length; i++) { 28792fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSkippedAlldayEvents[i] > 0) { 28802fda24534978f55711526dbde747aa50d68dec40RoboErik drawMoreAlldayEvents(canvas, mSkippedAlldayEvents[i], i, p); 28812fda24534978f55711526dbde747aa50d68dec40RoboErik } 28822fda24534978f55711526dbde747aa50d68dec40RoboErik } 28832fda24534978f55711526dbde747aa50d68dec40RoboErik } 2884146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 28852fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSelectionAllday) { 2886146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the neighbors for the list of all-day events that 2887146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // intersect the selected day. 2888146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeAllDayNeighbors(); 2889146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2890146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Set the selection position to zero so that when we move down 2891146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // to the normal event area, we will highlight the topmost event. 2892146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project saveSelectionPosition(0f, 0f, 0f, 0f); 2893146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2894146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2895146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 28962fda24534978f55711526dbde747aa50d68dec40RoboErik // Helper method for counting the number of allday events skipped on each day 28972fda24534978f55711526dbde747aa50d68dec40RoboErik private void incrementSkipCount(int[] counts, int startIndex, int endIndex) { 28982fda24534978f55711526dbde747aa50d68dec40RoboErik if (counts == null || startIndex < 0 || endIndex > counts.length) { 28992fda24534978f55711526dbde747aa50d68dec40RoboErik return; 29002fda24534978f55711526dbde747aa50d68dec40RoboErik } 29012fda24534978f55711526dbde747aa50d68dec40RoboErik for (int i = startIndex; i <= endIndex; i++) { 29022fda24534978f55711526dbde747aa50d68dec40RoboErik counts[i]++; 29032fda24534978f55711526dbde747aa50d68dec40RoboErik } 29042fda24534978f55711526dbde747aa50d68dec40RoboErik } 29052fda24534978f55711526dbde747aa50d68dec40RoboErik 29062fda24534978f55711526dbde747aa50d68dec40RoboErik // Draws the "box +n" text for hidden allday events 29072fda24534978f55711526dbde747aa50d68dec40RoboErik protected void drawMoreAlldayEvents(Canvas canvas, int remainingEvents, int day, Paint p) { 2908e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int x = computeDayLeftPosition(day) + EVENT_ALL_DAY_TEXT_LEFT_MARGIN; 2909e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int y = (int) (mAlldayHeight - .5f * MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT - .5f 2910e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * EVENT_SQUARE_WIDTH + DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN); 2911763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik Rect r = mRect; 2912763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.top = y; 2913763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.left = x; 2914763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.bottom = y + EVENT_SQUARE_WIDTH; 2915763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.right = x + EVENT_SQUARE_WIDTH; 2916e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setColor(mMoreEventsTextColor); 2917e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setStrokeWidth(EVENT_RECT_STROKE_WIDTH); 2918763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik p.setStyle(Style.STROKE); 2919e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 2920763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik canvas.drawRect(r, p); 2921e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(true); 2922763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik p.setStyle(Style.FILL); 2923763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik p.setTextSize(EVENT_TEXT_FONT_SIZE); 29242fda24534978f55711526dbde747aa50d68dec40RoboErik String text = mResources.getQuantityString(R.plurals.month_more_events, remainingEvents); 29252fda24534978f55711526dbde747aa50d68dec40RoboErik y += EVENT_SQUARE_WIDTH; 29262fda24534978f55711526dbde747aa50d68dec40RoboErik x += EVENT_SQUARE_WIDTH + EVENT_LINE_PADDING; 29272fda24534978f55711526dbde747aa50d68dec40RoboErik canvas.drawText(String.format(text, remainingEvents), x, y, p); 29282fda24534978f55711526dbde747aa50d68dec40RoboErik } 29292fda24534978f55711526dbde747aa50d68dec40RoboErik 2930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeAllDayNeighbors() { 2931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 2932146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len == 0 || mSelectedEvent != null) { 2933146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2934146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2935146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2936146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear all the links 2937146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2938146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2939146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = null; 2940146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = null; 2941146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = null; 2942146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = null; 2943146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2944146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2945146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each event in the selected event list "mSelectedEvents", find 294646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // its neighbors in the up and down directions. This could be done 2947146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // more efficiently by sorting on the Event.getColumn() field, but 2948146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the list is expected to be very small. 2949146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Find the event in the same row as the previously selected all-day 2951146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event, if any. 2952146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startPosition = -1; 295368655b5af2b7e5f872a103858ec58a19042123ceRoboErik if (mPrevSelectedEvent != null && mPrevSelectedEvent.drawAsAllday()) { 2954146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startPosition = mPrevSelectedEvent.getColumn(); 2955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2956146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxPosition = -1; 2957146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event startEvent = null; 2958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event maxPositionEvent = null; 2959146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 2960146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 2961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int position = ev.getColumn(); 2962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (position == startPosition) { 2963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEvent = ev; 2964146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (position > maxPosition) { 2965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxPositionEvent = ev; 2966146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxPosition = position; 2967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2968146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int jj = 0; jj < len; jj++) { 2969146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (jj == ii) { 2970146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2971146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2972146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event neighbor = mSelectedEvents.get(jj); 2973146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborPosition = neighbor.getColumn(); 2974146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborPosition == position - 1) { 2975146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = neighbor; 2976146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborPosition == position + 1) { 2977146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = neighbor; 2978146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2979146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2980146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2981146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (startEvent != null) { 2982146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = startEvent; 2983146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2984146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = maxPositionEvent; 2985146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2986146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2987146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2988e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private void drawEvents(int date, int dayIndex, int top, Canvas canvas, Paint p) { 2989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint eventTextPaint = mEventTextPaint; 2990763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik int left = computeDayLeftPosition(dayIndex) + 1; 2991763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik int cellWidth = computeDayLeftPosition(dayIndex + 1) - left + 1; 2992146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellHeight = mCellHeight; 2993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use the selected hour as the selection region 2995259b8f9a21fffd3858218581e9daaf689b6b888fErik Rect selectionArea = mSelectionRect; 2996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.top = top + mSelectionHour * (cellHeight + HOUR_GAP); 2997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.bottom = selectionArea.top + cellHeight; 2998146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.left = left; 2999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.right = selectionArea.left + cellWidth; 3000146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 300108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final ArrayList<Event> events = mEvents; 3002146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 3003146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project EventGeometry geometry = mEventGeometry; 3004146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 30052fda24534978f55711526dbde747aa50d68dec40RoboErik final int viewEndY = mViewStartY + mViewHeight - DAY_HEADER_HEIGHT - mAlldayHeight; 3006146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 3007146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 3008146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!geometry.computeEventRect(date, left, top, cellWidth, event)) { 3009146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3010146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3011146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 301208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Don't draw it if it is not visible 301308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (event.bottom < mViewStartY || event.top > viewEndY) { 301408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan continue; 301508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 301608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 30172fda24534978f55711526dbde747aa50d68dec40RoboErik if (date == mSelectionDay && !mSelectionAllday && mComputeSelectedEvents 3018146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && geometry.eventIntersectsSelection(event, selectionArea)) { 3019146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 3020146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3021146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 302225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik Rect r = drawEventRect(event, canvas, p, eventTextPaint, mViewStartY, viewEndY); 30231ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan setupTextRect(r); 302408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 302508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Don't draw text if it is not visible 302608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (r.top > viewEndY || r.bottom < mViewStartY) { 302708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan continue; 302808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 302908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = getEventLayout(mLayouts, i, event, eventTextPaint, r); 303008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // TODO: not sure why we are 4 pixels off 303146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan drawEventText(layout, r, canvas, mViewStartY + 4, mViewStartY + mViewHeight 30322fda24534978f55711526dbde747aa50d68dec40RoboErik - DAY_HEADER_HEIGHT - mAlldayHeight); 3033146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3034146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 30352fda24534978f55711526dbde747aa50d68dec40RoboErik if (date == mSelectionDay && !mSelectionAllday && isFocused() 3036146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && mSelectionMode != SELECTION_HIDDEN) { 3037146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeNeighbors(); 3038146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3039146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3040146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3041146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Computes the "nearest" neighbor event in four directions (left, right, 3042146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // up, down) for each of the events in the mSelectedEvents array. 3043146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeNeighbors() { 3044146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 3045146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len == 0 || mSelectedEvent != null) { 3046146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3047146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3048146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3049146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear all the links 3050146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 3051146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 3052146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = null; 3053146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = null; 3054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = null; 3055146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = null; 3056146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3057146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3058146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event startEvent = mSelectedEvents.get(0); 305946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int startEventDistance1 = 100000; // any large number 306046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int startEventDistance2 = 100000; // any large number 3061146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevLocation = FROM_NONE; 3062146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevTop; 3063146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevBottom; 3064146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevLeft; 3065146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevRight; 3066146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevCenter = 0; 3067146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect box = getCurrentSelectionPosition(); 3068146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPrevSelectedEvent != null) { 3069146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = (int) mPrevSelectedEvent.top; 3070146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = (int) mPrevSelectedEvent.bottom; 3071146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = (int) mPrevSelectedEvent.left; 3072146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = (int) mPrevSelectedEvent.right; 3073146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check if the previously selected event intersects the previous 307446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // selection box. (The previously selected event may be from a 3075146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // much older selection box.) 3076146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevTop >= mPrevBox.bottom || prevBottom <= mPrevBox.top 3077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || prevRight <= mPrevBox.left || prevLeft >= mPrevBox.right) { 3078146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 3079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 3080146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 3081146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = mPrevBox.left; 3082146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = mPrevBox.right; 3083146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3084146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Clip the top and bottom to the previous selection box. 3085146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevTop < mPrevBox.top) { 3086146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 3087146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3088146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevBottom > mPrevBox.bottom) { 3089146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 3090146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3091146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3092146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3093146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Just use the previously drawn selection box 3094146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 3095146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 3096146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = mPrevBox.left; 3097146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = mPrevBox.right; 3098146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out where we came from and compute the center of that area. 3101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevLeft >= box.right) { 3102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was to the right of us. 3103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_RIGHT; 3104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevTop + prevBottom) / 2; 3105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevRight <= box.left) { 3106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was to the left of us. 3107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_LEFT; 3108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevTop + prevBottom) / 2; 3109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevBottom <= box.top) { 3110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was above us. 3111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_ABOVE; 3112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevLeft + prevRight) / 2; 3113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevTop >= box.bottom) { 3114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was below us. 3115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_BELOW; 3116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevLeft + prevRight) / 2; 3117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each event in the selected event list "mSelectedEvents", search 3120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // all the other events in that list for the nearest neighbor in 4 3121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // directions. 3122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 3123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 3124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startTime = ev.startTime; 3126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endTime = ev.endTime; 3127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int left = (int) ev.left; 3128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int right = (int) ev.right; 3129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int top = (int) ev.top; 3130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (top < box.top) { 3131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project top = box.top; 3132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int bottom = (int) ev.bottom; 3134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom > box.bottom) { 3135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project bottom = box.bottom; 3136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 313721bd42039c92232647f54461cd20708224cc7eb6Michael Chan// if (false) { 313821bd42039c92232647f54461cd20708224cc7eb6Michael Chan// int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL 313921bd42039c92232647f54461cd20708224cc7eb6Michael Chan// | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 314021bd42039c92232647f54461cd20708224cc7eb6Michael Chan// if (DateFormat.is24HourFormat(mContext)) { 314121bd42039c92232647f54461cd20708224cc7eb6Michael Chan// flags |= DateUtils.FORMAT_24HOUR; 314221bd42039c92232647f54461cd20708224cc7eb6Michael Chan// } 314321bd42039c92232647f54461cd20708224cc7eb6Michael Chan// String timeRange = DateUtils.formatDateRange(mContext, ev.startMillis, 314421bd42039c92232647f54461cd20708224cc7eb6Michael Chan// ev.endMillis, flags); 314521bd42039c92232647f54461cd20708224cc7eb6Michael Chan// Log.i("Cal", "left: " + left + " right: " + right + " top: " + top + " bottom: " 314621bd42039c92232647f54461cd20708224cc7eb6Michael Chan// + bottom + " ev: " + timeRange + " " + ev.title); 314721bd42039c92232647f54461cd20708224cc7eb6Michael Chan// } 314846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int upDistanceMin = 10000; // any large number 314946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int downDistanceMin = 10000; // any large number 315046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int leftDistanceMin = 10000; // any large number 315146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int rightDistanceMin = 10000; // any large number 3152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event upEvent = null; 3153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event downEvent = null; 3154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event leftEvent = null; 3155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event rightEvent = null; 3156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the starting event closest to the previously selected event, 315846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // if any. distance1 takes precedence over distance2. 3159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance1 = 0; 3160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance2 = 0; 3161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevLocation == FROM_ABOVE) { 3162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (left >= prevCenter) { 3163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = left - prevCenter; 3164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (right <= prevCenter) { 3165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - right; 3166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = top - prevBottom; 3168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_BELOW) { 3169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (left >= prevCenter) { 3170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = left - prevCenter; 3171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (right <= prevCenter) { 3172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - right; 3173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = prevTop - bottom; 3175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_LEFT) { 3176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom <= prevCenter) { 3177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - bottom; 3178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (top >= prevCenter) { 3179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = top - prevCenter; 3180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = left - prevRight; 3182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_RIGHT) { 3183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom <= prevCenter) { 3184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - bottom; 3185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (top >= prevCenter) { 3186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = top - prevCenter; 3187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = prevLeft - right; 3189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance1 < startEventDistance1 3191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || (distance1 == startEventDistance1 && distance2 < startEventDistance2)) { 3192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEvent = ev; 3193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEventDistance1 = distance1; 3194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEventDistance2 = distance2; 3195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each neighbor, figure out if it is above or below or left 3198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // or right of me and compute the distance. 3199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int jj = 0; jj < len; jj++) { 3200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (jj == ii) { 3201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event neighbor = mSelectedEvents.get(jj); 3204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborLeft = (int) neighbor.left; 3205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborRight = (int) neighbor.right; 3206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighbor.endTime <= startTime) { 3207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely above me. 3208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we overlap the same column, then compute the distance. 3209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft < right && neighborRight > left) { 3210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = startTime - neighbor.endTime; 3211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < upDistanceMin) { 3212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upDistanceMin = distance; 3213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upEvent = neighbor; 3214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == upDistanceMin) { 3215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (left + right) / 2; 3216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = 0; 3217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentLeft = (int) upEvent.left; 3218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentRight = (int) upEvent.right; 3219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (currentRight <= center) { 3220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = center - currentRight; 3221146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (currentLeft >= center) { 3222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = currentLeft - center; 3223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = 0; 3226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborRight <= center) { 3227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = center - neighborRight; 3228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborLeft >= center) { 3229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = neighborLeft - center; 3230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 3232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upDistanceMin = distance; 3233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upEvent = neighbor; 3234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighbor.startTime >= endTime) { 3238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely below me. 3239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we overlap the same column, then compute the distance. 3240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft < right && neighborRight > left) { 3241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = neighbor.startTime - endTime; 3242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < downDistanceMin) { 3243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downDistanceMin = distance; 3244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downEvent = neighbor; 3245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == downDistanceMin) { 3246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (left + right) / 2; 3247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = 0; 3248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentLeft = (int) downEvent.left; 3249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentRight = (int) downEvent.right; 3250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (currentRight <= center) { 3251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = center - currentRight; 3252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (currentLeft >= center) { 3253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = currentLeft - center; 3254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = 0; 3257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborRight <= center) { 3258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = center - neighborRight; 3259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborLeft >= center) { 3260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = neighborLeft - center; 3261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 3263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downDistanceMin = distance; 3264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downEvent = neighbor; 3265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft >= right) { 3271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely to the right of me. 3272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Take the closest neighbor in the y direction. 3273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (top + bottom) / 2; 3274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = 0; 3275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborBottom = (int) neighbor.bottom; 3276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborTop = (int) neighbor.top; 3277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborBottom <= center) { 3278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = center - neighborBottom; 3279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborTop >= center) { 3280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = neighborTop - center; 3281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < rightDistanceMin) { 3283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightDistanceMin = distance; 3284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightEvent = neighbor; 3285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == rightDistanceMin) { 3286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the closest in the x direction 3287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = neighborLeft - right; 3288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = (int) rightEvent.left - right; 3289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 3290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightDistanceMin = distance; 3291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightEvent = neighbor; 3292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborRight <= left) { 3295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely to the left of me. 3296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Take the closest neighbor in the y direction. 3297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (top + bottom) / 2; 3298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = 0; 3299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborBottom = (int) neighbor.bottom; 3300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborTop = (int) neighbor.top; 3301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborBottom <= center) { 3302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = center - neighborBottom; 3303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborTop >= center) { 3304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = neighborTop - center; 3305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < leftDistanceMin) { 3307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftDistanceMin = distance; 3308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftEvent = neighbor; 3309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == leftDistanceMin) { 3310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the closest in the x direction 3311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = left - neighborRight; 3312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = left - (int) leftEvent.right; 3313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 3314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftDistanceMin = distance; 3315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftEvent = neighbor; 3316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = upEvent; 3321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = downEvent; 3322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = leftEvent; 3323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = rightEvent; 3324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = startEvent; 3326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 332825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private Rect drawEventRect(Event event, Canvas canvas, Paint p, Paint eventTextPaint, 332925996100d6ea61888ebe54d7708a9a371bb12a55RoboErik int visibleTop, int visibleBot) { 333011ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw the Event Rect 33311ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Rect r = mRect; 333225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik r.top = Math.max((int) event.top + EVENT_RECT_TOP_MARGIN, visibleTop); 333325996100d6ea61888ebe54d7708a9a371bb12a55RoboErik r.bottom = Math.min((int) event.bottom - EVENT_RECT_BOTTOM_MARGIN, visibleBot); 33341ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = (int) event.left + EVENT_RECT_LEFT_MARGIN; 333525996100d6ea61888ebe54d7708a9a371bb12a55RoboErik r.right = (int) event.right; 33361ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 3337aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan int color = event.color; 3338f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan switch (event.selfAttendeeStatus) { 3339f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_INVITED: 334025996100d6ea61888ebe54d7708a9a371bb12a55RoboErik p.setStyle(Style.STROKE); 334125996100d6ea61888ebe54d7708a9a371bb12a55RoboErik break; 3342f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_DECLINED: 33433c40e07972c989719723e24db6d5d8812200823bRoboErik color = Utils.getDeclinedColorFromColor(color); 3344f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_NONE: // Your own events 3345f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_ACCEPTED: 3346f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_TENTATIVE: 3347f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan default: 334825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik p.setStyle(Style.FILL_AND_STROKE); 3349f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan break; 3350f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan } 3351e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 3352e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 3353e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 3354aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan int floorHalfStroke = (int) Math.floor(EVENT_RECT_STROKE_WIDTH / 2.0f); 3355aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan int ceilHalfStroke = (int) Math.ceil(EVENT_RECT_STROKE_WIDTH / 2.0f); 3356aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan r.top = Math.max((int) event.top + EVENT_RECT_TOP_MARGIN + floorHalfStroke, visibleTop); 3357aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan r.bottom = Math.min((int) event.bottom - EVENT_RECT_BOTTOM_MARGIN - ceilHalfStroke, 3358aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan visibleBot); 3359aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan r.left += floorHalfStroke; 3360aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan r.right -= ceilHalfStroke; 3361aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan p.setStrokeWidth(EVENT_RECT_STROKE_WIDTH); 3362aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan p.setColor(color); 3363aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan canvas.drawRect(r, p); 3364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 33651ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setStyle(Style.FILL); 3366e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If this event is selected, then use the selection color 3368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == event) { 33691ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan boolean paintIt = false; 3370aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan color = 0; 3371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_PRESSED) { 3372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 3373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 337478f58c119af15ed85a727e16cddd793ced4c809dMichael Chan color = mPressedColor; 33751ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan paintIt = true; 3376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionMode == SELECTION_SELECTED) { 3377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 3378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 337978f58c119af15ed85a727e16cddd793ced4c809dMichael Chan color = mPressedColor; 33801ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan paintIt = true; 33811ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan } 33821ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 33831ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (paintIt) { 33841ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setColor(color); 33851ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawRect(r, p); 3386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3387e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 3388e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(true); 3389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 339111ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw cal color square border 339225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.top = (int) event.top + CALENDAR_COLOR_SQUARE_V_OFFSET; 339325996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.left = (int) event.left + CALENDAR_COLOR_SQUARE_H_OFFSET; 339425996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.bottom = r.top + CALENDAR_COLOR_SQUARE_SIZE + 1; 339525996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.right = r.left + CALENDAR_COLOR_SQUARE_SIZE + 1; 339625996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // p.setColor(0xFFFFFFFF); 339725996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // canvas.drawRect(r, p); 33988af2529989a9b10a0bb84736695c22fc02a17a4aThe Android Open Source Project 339911ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw cal color 340025996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.top++; 340125996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.left++; 340225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.bottom--; 340325996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.right--; 340425996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // p.setColor(event.color); 340525996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // canvas.drawRect(r, p); 3406e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 34073eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Setup rect for drawEventText which follows 34081ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top = (int) event.top + EVENT_RECT_TOP_MARGIN; 34091ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = (int) event.bottom - EVENT_RECT_BOTTOM_MARGIN; 34101ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = (int) event.left + EVENT_RECT_LEFT_MARGIN; 34111ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = (int) event.right - EVENT_RECT_RIGHT_MARGIN; 34121ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan return r; 3413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 34150d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan private Pattern drawTextSanitizerFilter = Pattern.compile("[\t\n],"); 34160d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 34170d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // Sanitize a string before passing it to drawText or else we get little 34180d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // squares. For newlines and tabs before a comma, delete the character. 34190d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // Otherwise, just replace them with a space. 3420f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan private String drawTextSanitizer(String string, int maxEventTextLen) { 34210d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan Matcher m = drawTextSanitizerFilter.matcher(string); 3422f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan string = m.replaceAll(","); 3423f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan 3424f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan int len = string.length(); 34251c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik if (maxEventTextLen <= 0) { 34261c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik string = ""; 34271c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik len = 0; 34281c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik } else if (len > maxEventTextLen) { 3429f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan string = string.substring(0, maxEventTextLen); 3430f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan len = maxEventTextLen; 3431f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan } 3432f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan 3433f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan return string.replace('\n', ' '); 34340d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan } 34350d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 343608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private void drawEventText(StaticLayout eventLayout, Rect rect, Canvas canvas, int top, 343708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan int bottom) { 34381ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // drawEmptyRect(canvas, rect, 0xFFFF00FF); // for debugging 34391ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 34401ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int width = rect.right - rect.left; 34411ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int height = rect.bottom - rect.top; 3442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the rectangle is too small for text, then return 34440a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan if (eventLayout == null || width < MIN_CELL_WIDTH_FOR_TEXT) { 3445f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan return; 3446f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 3447f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan 344808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan int totalLineHeight = 0; 3449f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan int lineCount = eventLayout.getLineCount(); 3450f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan for (int i = 0; i < lineCount; i++) { 3451f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan int lineBottom = eventLayout.getLineBottom(i); 3452f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan if (lineBottom <= height) { 345308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan totalLineHeight = lineBottom; 345408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 345508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan break; 3456f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 3457f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 3458f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan 345908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (totalLineHeight == 0 || rect.top > bottom || rect.top + totalLineHeight < top) { 3460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 34633e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh // Use a StaticLayout to format the string. 34643e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh canvas.save(); 34651ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.translate(rect.left, rect.top); 34661ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.left = 0; 34671ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.right = width; 34681ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.top = 0; 346908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan rect.bottom = totalLineHeight; 347008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 347108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // There's a bug somewhere. If this rect is outside of a previous 347208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // cliprect, this becomes a no-op. What happens is that the text draw 347308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // past the event rect. The current fix is to not draw the staticLayout 347408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // at all if it is completely out of bound. 34751ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.clipRect(rect); 34763e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh eventLayout.draw(canvas); 34773e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh canvas.restore(); 3478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 34801ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // This is to replace p.setStyle(Style.STROKE); canvas.drawRect() since it 34811ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // doesn't work well with hardware acceleration 348221bd42039c92232647f54461cd20708224cc7eb6Michael Chan// private void drawEmptyRect(Canvas canvas, Rect r, int color) { 348321bd42039c92232647f54461cd20708224cc7eb6Michael Chan// int linesIndex = 0; 348421bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.left; 348521bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.top; 348621bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.right; 348721bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.top; 348821bd42039c92232647f54461cd20708224cc7eb6Michael Chan// 348921bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.left; 349021bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.bottom; 349121bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.right; 349221bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.bottom; 349321bd42039c92232647f54461cd20708224cc7eb6Michael Chan// 349421bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.left; 349521bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.top; 349621bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.left; 349721bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.bottom; 349821bd42039c92232647f54461cd20708224cc7eb6Michael Chan// 349921bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.right; 350021bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.top; 350121bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.right; 350221bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.bottom; 350321bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mPaint.setColor(color); 350421bd42039c92232647f54461cd20708224cc7eb6Michael Chan// canvas.drawLines(mLines, 0, linesIndex, mPaint); 350521bd42039c92232647f54461cd20708224cc7eb6Michael Chan// } 35061ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 3507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void updateEventDetails() { 3508146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null || mSelectionMode == SELECTION_HIDDEN 3509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || mSelectionMode == SELECTION_LONGPRESS) { 3510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3512146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3513666fc5e8ddbac15c951aad738bd818ee307eae42Erik if (mLastPopupEventID == mSelectedEvent.id) { 3514666fc5e8ddbac15c951aad738bd818ee307eae42Erik return; 3515666fc5e8ddbac15c951aad738bd818ee307eae42Erik } 3516666fc5e8ddbac15c951aad738bd818ee307eae42Erik 3517666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = mSelectedEvent.id; 3518146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3519146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Remove any outstanding callbacks to dismiss the popup. 3520ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.removeCallbacks(mDismissPopup); 3521146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3522146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = mSelectedEvent; 3523146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView titleView = (TextView) mPopupView.findViewById(R.id.event_title); 3524146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project titleView.setText(event.title); 3525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ImageView imageView = (ImageView) mPopupView.findViewById(R.id.reminder_icon); 3527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView.setVisibility(event.hasAlarm ? View.VISIBLE : View.GONE); 3528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView = (ImageView) mPopupView.findViewById(R.id.repeat_icon); 3530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView.setVisibility(event.isRepeating ? View.VISIBLE : View.GONE); 3531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags; 3533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.allDay) { 353446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan flags = DateUtils.FORMAT_UTC | DateUtils.FORMAT_SHOW_DATE 353546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_ALL; 3536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE 3538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_ALL 3539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 3540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3541ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (DateFormat.is24HourFormat(mContext)) { 3542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags |= DateUtils.FORMAT_24HOUR; 3543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 354446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan String timeRange = Utils.formatDateRange(mContext, event.startMillis, event.endMillis, 354546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan flags); 3546146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView timeView = (TextView) mPopupView.findViewById(R.id.time); 3547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project timeView.setText(timeRange); 3548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView whereView = (TextView) mPopupView.findViewById(R.id.where); 3550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final boolean empty = TextUtils.isEmpty(event.location); 3551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project whereView.setVisibility(empty ? View.GONE : View.VISIBLE); 3552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!empty) whereView.setText(event.location); 3553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.showAtLocation(this, Gravity.BOTTOM | Gravity.LEFT, mHoursWidth, 5); 3555ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.postDelayed(mDismissPopup, POPUP_DISMISS_DELAY); 3556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The following routines are called from the parent activity when certain 3559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // touch events occur. 35604484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doDown(MotionEvent ev) { 3561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_DOWN; 3562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = 0; 3563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mOnFlingCalled = false; 3564ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.removeCallbacks(mContinueScroll); 3565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 35672fda24534978f55711526dbde747aa50d68dec40RoboErik // Kicks off all the animations when the expand allday area is tapped 35682fda24534978f55711526dbde747aa50d68dec40RoboErik private void doExpandAllDayClick() { 35692fda24534978f55711526dbde747aa50d68dec40RoboErik mShowAllAllDayEvents = !mShowAllAllDayEvents; 35702fda24534978f55711526dbde747aa50d68dec40RoboErik 35712fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator.setFrameDelay(0); 35722fda24534978f55711526dbde747aa50d68dec40RoboErik 35732fda24534978f55711526dbde747aa50d68dec40RoboErik // Determine the starting height 35742fda24534978f55711526dbde747aa50d68dec40RoboErik if (mAnimateDayHeight == 0) { 35752fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayHeight = mShowAllAllDayEvents ? 35762fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayHeight - (int) MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT : mAlldayHeight; 35772fda24534978f55711526dbde747aa50d68dec40RoboErik } 35782fda24534978f55711526dbde747aa50d68dec40RoboErik // Cancel current animations 35792fda24534978f55711526dbde747aa50d68dec40RoboErik mCancellingAnimations = true; 35802fda24534978f55711526dbde747aa50d68dec40RoboErik if (mAlldayAnimator != null) { 35812fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayAnimator.cancel(); 35822fda24534978f55711526dbde747aa50d68dec40RoboErik } 35832fda24534978f55711526dbde747aa50d68dec40RoboErik if (mAlldayEventAnimator != null) { 35842fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayEventAnimator.cancel(); 35852fda24534978f55711526dbde747aa50d68dec40RoboErik } 35862fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMoreAlldayEventsAnimator != null) { 35872fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsAnimator.cancel(); 35882fda24534978f55711526dbde747aa50d68dec40RoboErik } 35892fda24534978f55711526dbde747aa50d68dec40RoboErik mCancellingAnimations = false; 35902fda24534978f55711526dbde747aa50d68dec40RoboErik // get new animators 35912fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayAnimator = getAllDayAnimator(); 35922fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayEventAnimator = getAllDayEventAnimator(); 35932fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsAnimator = ObjectAnimator.ofInt(this, 35942fda24534978f55711526dbde747aa50d68dec40RoboErik "moreAllDayEventsTextAlpha", 35952fda24534978f55711526dbde747aa50d68dec40RoboErik mShowAllAllDayEvents ? MORE_EVENTS_MAX_ALPHA : 0, 35962fda24534978f55711526dbde747aa50d68dec40RoboErik mShowAllAllDayEvents ? 0 : MORE_EVENTS_MAX_ALPHA); 35972fda24534978f55711526dbde747aa50d68dec40RoboErik 35982fda24534978f55711526dbde747aa50d68dec40RoboErik // Set up delays and start the animators 35992fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayAnimator.setStartDelay(mShowAllAllDayEvents ? ANIMATION_SECONDARY_DURATION : 0); 36002fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayAnimator.start(); 36012fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsAnimator.setStartDelay(mShowAllAllDayEvents ? 0 : ANIMATION_DURATION); 36022fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsAnimator.setDuration(ANIMATION_SECONDARY_DURATION); 36032fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsAnimator.start(); 36042fda24534978f55711526dbde747aa50d68dec40RoboErik if (mAlldayEventAnimator != null) { 36052fda24534978f55711526dbde747aa50d68dec40RoboErik // This is the only animator that can return null, so check it 36062fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayEventAnimator 36072fda24534978f55711526dbde747aa50d68dec40RoboErik .setStartDelay(mShowAllAllDayEvents ? ANIMATION_SECONDARY_DURATION : 0); 36082fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayEventAnimator.start(); 36092fda24534978f55711526dbde747aa50d68dec40RoboErik } 36102fda24534978f55711526dbde747aa50d68dec40RoboErik } 36112fda24534978f55711526dbde747aa50d68dec40RoboErik 36122fda24534978f55711526dbde747aa50d68dec40RoboErik /** 36132fda24534978f55711526dbde747aa50d68dec40RoboErik * Figures out the initial heights for allDay events and space when 36142fda24534978f55711526dbde747aa50d68dec40RoboErik * a view is being set up. 36152fda24534978f55711526dbde747aa50d68dec40RoboErik */ 36162fda24534978f55711526dbde747aa50d68dec40RoboErik public void initAllDayHeights() { 36172fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents <= mMaxUnexpandedAlldayEventCount) { 36182fda24534978f55711526dbde747aa50d68dec40RoboErik return; 36192fda24534978f55711526dbde747aa50d68dec40RoboErik } 36202fda24534978f55711526dbde747aa50d68dec40RoboErik if (mShowAllAllDayEvents) { 36212fda24534978f55711526dbde747aa50d68dec40RoboErik int maxADHeight = mViewHeight - DAY_HEADER_HEIGHT - MIN_HOURS_HEIGHT; 36222fda24534978f55711526dbde747aa50d68dec40RoboErik maxADHeight = Math.min(maxADHeight, 36232fda24534978f55711526dbde747aa50d68dec40RoboErik (int)(mMaxAlldayEvents * MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT)); 36242fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayEventHeight = maxADHeight / mMaxAlldayEvents; 36252fda24534978f55711526dbde747aa50d68dec40RoboErik } else { 36262fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayEventHeight = (int)MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT; 36272fda24534978f55711526dbde747aa50d68dec40RoboErik } 36282fda24534978f55711526dbde747aa50d68dec40RoboErik } 36292fda24534978f55711526dbde747aa50d68dec40RoboErik 36302fda24534978f55711526dbde747aa50d68dec40RoboErik // Sets up an animator for changing the height of allday events 36312fda24534978f55711526dbde747aa50d68dec40RoboErik private ObjectAnimator getAllDayEventAnimator() { 36322fda24534978f55711526dbde747aa50d68dec40RoboErik // First calculate the absolute max height 36332fda24534978f55711526dbde747aa50d68dec40RoboErik int maxADHeight = mViewHeight - DAY_HEADER_HEIGHT - MIN_HOURS_HEIGHT; 36342fda24534978f55711526dbde747aa50d68dec40RoboErik // Now expand to fit but not beyond the absolute max 36352fda24534978f55711526dbde747aa50d68dec40RoboErik maxADHeight = 36362fda24534978f55711526dbde747aa50d68dec40RoboErik Math.min(maxADHeight, (int)(mMaxAlldayEvents * MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT)); 36372fda24534978f55711526dbde747aa50d68dec40RoboErik // calculate the height of individual events in order to fit 36382fda24534978f55711526dbde747aa50d68dec40RoboErik int fitHeight = maxADHeight / mMaxAlldayEvents; 36392fda24534978f55711526dbde747aa50d68dec40RoboErik int currentHeight = mAnimateDayEventHeight; 36402fda24534978f55711526dbde747aa50d68dec40RoboErik int desiredHeight = 36412fda24534978f55711526dbde747aa50d68dec40RoboErik mShowAllAllDayEvents ? fitHeight : (int)MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT; 36422fda24534978f55711526dbde747aa50d68dec40RoboErik // if there's nothing to animate just return 36432fda24534978f55711526dbde747aa50d68dec40RoboErik if (currentHeight == desiredHeight) { 36442fda24534978f55711526dbde747aa50d68dec40RoboErik return null; 36452fda24534978f55711526dbde747aa50d68dec40RoboErik } 36462fda24534978f55711526dbde747aa50d68dec40RoboErik 36472fda24534978f55711526dbde747aa50d68dec40RoboErik // Set up the animator with the calculated values 36482fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator animator = ObjectAnimator.ofInt(this, "animateDayEventHeight", 36492fda24534978f55711526dbde747aa50d68dec40RoboErik currentHeight, desiredHeight); 36502fda24534978f55711526dbde747aa50d68dec40RoboErik animator.setDuration(ANIMATION_DURATION); 36512fda24534978f55711526dbde747aa50d68dec40RoboErik return animator; 36522fda24534978f55711526dbde747aa50d68dec40RoboErik } 36532fda24534978f55711526dbde747aa50d68dec40RoboErik 36542fda24534978f55711526dbde747aa50d68dec40RoboErik // Sets up an animator for changing the height of the allday area 36552fda24534978f55711526dbde747aa50d68dec40RoboErik private ObjectAnimator getAllDayAnimator() { 36562fda24534978f55711526dbde747aa50d68dec40RoboErik // Calculate the absolute max height 36572fda24534978f55711526dbde747aa50d68dec40RoboErik int maxADHeight = mViewHeight - DAY_HEADER_HEIGHT - MIN_HOURS_HEIGHT; 36582fda24534978f55711526dbde747aa50d68dec40RoboErik // Find the desired height but don't exceed abs max 36592fda24534978f55711526dbde747aa50d68dec40RoboErik maxADHeight = 36602fda24534978f55711526dbde747aa50d68dec40RoboErik Math.min(maxADHeight, (int)(mMaxAlldayEvents * MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT)); 36612fda24534978f55711526dbde747aa50d68dec40RoboErik // calculate the current and desired heights 36622fda24534978f55711526dbde747aa50d68dec40RoboErik int currentHeight = mAnimateDayHeight != 0 ? mAnimateDayHeight : mAlldayHeight; 36632fda24534978f55711526dbde747aa50d68dec40RoboErik int desiredHeight = mShowAllAllDayEvents ? maxADHeight : 36642fda24534978f55711526dbde747aa50d68dec40RoboErik (int) (MAX_UNEXPANDED_ALLDAY_HEIGHT - MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT - 1); 36652fda24534978f55711526dbde747aa50d68dec40RoboErik 36662fda24534978f55711526dbde747aa50d68dec40RoboErik // Set up the animator with the calculated values 36672fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator animator = ObjectAnimator.ofInt(this, "animateDayHeight", 36682fda24534978f55711526dbde747aa50d68dec40RoboErik currentHeight, desiredHeight); 36692fda24534978f55711526dbde747aa50d68dec40RoboErik animator.setDuration(ANIMATION_DURATION); 36702fda24534978f55711526dbde747aa50d68dec40RoboErik 36712fda24534978f55711526dbde747aa50d68dec40RoboErik animator.addListener(new AnimatorListenerAdapter() { 36722fda24534978f55711526dbde747aa50d68dec40RoboErik @Override 36732fda24534978f55711526dbde747aa50d68dec40RoboErik public void onAnimationEnd(Animator animation) { 36742fda24534978f55711526dbde747aa50d68dec40RoboErik if (!mCancellingAnimations) { 36752fda24534978f55711526dbde747aa50d68dec40RoboErik // when finished, set this to 0 to signify not animating 36762fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayHeight = 0; 3677cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mUseExpandIcon = !mShowAllAllDayEvents; 36782fda24534978f55711526dbde747aa50d68dec40RoboErik } 36792fda24534978f55711526dbde747aa50d68dec40RoboErik mRemeasure = true; 36802fda24534978f55711526dbde747aa50d68dec40RoboErik invalidate(); 36812fda24534978f55711526dbde747aa50d68dec40RoboErik } 36822fda24534978f55711526dbde747aa50d68dec40RoboErik }); 36832fda24534978f55711526dbde747aa50d68dec40RoboErik return animator; 36842fda24534978f55711526dbde747aa50d68dec40RoboErik } 36852fda24534978f55711526dbde747aa50d68dec40RoboErik 36862fda24534978f55711526dbde747aa50d68dec40RoboErik // setter for the 'box +n' alpha text used by the animator 36872fda24534978f55711526dbde747aa50d68dec40RoboErik public void setMoreAllDayEventsTextAlpha(int alpha) { 36882fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsTextAlpha = alpha; 36892fda24534978f55711526dbde747aa50d68dec40RoboErik invalidate(); 36902fda24534978f55711526dbde747aa50d68dec40RoboErik } 36912fda24534978f55711526dbde747aa50d68dec40RoboErik 36922fda24534978f55711526dbde747aa50d68dec40RoboErik // setter for the height of the allday area used by the animator 36932fda24534978f55711526dbde747aa50d68dec40RoboErik public void setAnimateDayHeight(int height) { 36942fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayHeight = height; 36952fda24534978f55711526dbde747aa50d68dec40RoboErik mRemeasure = true; 36962fda24534978f55711526dbde747aa50d68dec40RoboErik invalidate(); 36972fda24534978f55711526dbde747aa50d68dec40RoboErik } 36982fda24534978f55711526dbde747aa50d68dec40RoboErik 36992fda24534978f55711526dbde747aa50d68dec40RoboErik // setter for the height of allday events used by the animator 37002fda24534978f55711526dbde747aa50d68dec40RoboErik public void setAnimateDayEventHeight(int height) { 37012fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayEventHeight = height; 37022fda24534978f55711526dbde747aa50d68dec40RoboErik mRemeasure = true; 37032fda24534978f55711526dbde747aa50d68dec40RoboErik invalidate(); 37042fda24534978f55711526dbde747aa50d68dec40RoboErik } 37052fda24534978f55711526dbde747aa50d68dec40RoboErik 37064484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doSingleTapUp(MotionEvent ev) { 3707bbf2cbdb040108da50d763b699836e5f63fb7cceMichael Chan if (!mHandleActionUp || mScrolling) { 3708d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return; 3709d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3710d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3711146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int x = (int) ev.getX(); 3712146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = (int) ev.getY(); 3713146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectedDay = mSelectionDay; 3714146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectedHour = mSelectionHour; 3715146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 37162fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount) { 37172fda24534978f55711526dbde747aa50d68dec40RoboErik // check if the tap was in the allday expansion area 37184ab51bf9fc2f3e6915705f39688e8244fc74028fRoboErik int bottom = mFirstCell; 37192fda24534978f55711526dbde747aa50d68dec40RoboErik if((x < mHoursWidth && y > DAY_HEADER_HEIGHT && y < DAY_HEADER_HEIGHT + mAlldayHeight) 37202fda24534978f55711526dbde747aa50d68dec40RoboErik || (!mShowAllAllDayEvents && mAnimateDayHeight == 0 && y < bottom && 37212fda24534978f55711526dbde747aa50d68dec40RoboErik y >= bottom - MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT)) { 37222fda24534978f55711526dbde747aa50d68dec40RoboErik doExpandAllDayClick(); 37232fda24534978f55711526dbde747aa50d68dec40RoboErik return; 37242fda24534978f55711526dbde747aa50d68dec40RoboErik } 37252fda24534978f55711526dbde747aa50d68dec40RoboErik } 37262fda24534978f55711526dbde747aa50d68dec40RoboErik 3727146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean validPosition = setSelectionFromPosition(x, y); 3728146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!validPosition) { 3729360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan if (y < DAY_HEADER_HEIGHT) { 3730360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan Time selectedTime = new Time(mBaseDate); 3731360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan selectedTime.setJulianDay(mSelectionDay); 3732360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan selectedTime.hour = mSelectionHour; 3733360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan selectedTime.normalize(true /* ignore isDst */); 3734360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan mController.sendEvent(this, EventType.GO_TO, null, null, selectedTime, -1, 3735360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan ViewType.DAY, CalendarController.EXTRA_GOTO_DATE, null, null); 3736360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan } 3737146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3738146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3739146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3740b6fb51224b578b26e503fddae2799d03a2aaad47RoboErik boolean hasSelection = mSelectionMode != SELECTION_HIDDEN; 374195f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan boolean pressedSelected = (hasSelection || mTouchExplorationEnabled) 374295f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan && selectedDay == mSelectionDay && selectedHour == mSelectionHour; 3743146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 374495f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan if (pressedSelected) { 3745344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan // If the tap is on an already selected hour slot, then create a new 3746344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan // event 3747edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan long extraLong = 0; 3748edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan if (mSelectionAllday) { 3749edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan extraLong = CalendarController.EXTRA_CREATE_ALL_DAY; 3750edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan } 375195f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan mSelectionMode = SELECTION_SELECTED; 3752edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan mController.sendEventRelatedEventWithExtra(this, EventType.CREATE_EVENT, -1, 3753edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan getSelectedTimeInMillis(), 0, (int) ev.getRawX(), (int) ev.getRawY(), 3754edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan extraLong, -1); 375595f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan } else if (mSelectedEvent != null) { 375695f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan // If the tap is on an event, launch the "View event" view 375795f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan if (mIsAccessibilityEnabled) { 375895f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan mAccessibilityMgr.interrupt(); 375995f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan } 376095f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan 376195f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan mSelectionMode = SELECTION_HIDDEN; 37620aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson 37630aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson int yLocation = 37640aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson (int)((mSelectedEvent.top + mSelectedEvent.bottom)/2); 37650aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson // Y location is affected by the position of the event in the scrolling 37660aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson // view (mViewStartY) and the presence of all day events (mFirstCell) 37670aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson if (!mSelectedEvent.allDay) { 37680aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson yLocation += (mFirstCell - mViewStartY); 37690aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson } 377095f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, mSelectedEvent.id, 37710aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson mSelectedEvent.startMillis, mSelectedEvent.endMillis, 37720aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson (int)((mSelectedEvent.left + mSelectedEvent.right)/2), 37730aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson yLocation, getSelectedTimeInMillis()); 3774344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan } else { 377595f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan // Select time 3776344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan Time startTime = new Time(mBaseDate); 3777344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.setJulianDay(mSelectionDay); 3778344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.hour = mSelectionHour; 3779344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.normalize(true /* ignore isDst */); 378083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 378183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time endTime = new Time(startTime); 378283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan endTime.hour++; 378383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 378495f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan mSelectionMode = SELECTION_SELECTED; 378546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mController.sendEvent(this, EventType.GO_TO, startTime, endTime, -1, ViewType.CURRENT, 378646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan CalendarController.EXTRA_GOTO_TIME, null, null); 3787146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 378895f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan invalidate(); 3789146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3790146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 37914484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doLongPress(MotionEvent ev) { 3792bbf2cbdb040108da50d763b699836e5f63fb7cceMichael Chan if (mScrolling) { 3793bbf2cbdb040108da50d763b699836e5f63fb7cceMichael Chan return; 3794bbf2cbdb040108da50d763b699836e5f63fb7cceMichael Chan } 3795bbf2cbdb040108da50d763b699836e5f63fb7cceMichael Chan 3796d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // Scale gesture in progress 3797d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mStartingSpanY != 0) { 3798d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return; 3799d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3800d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 380180bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan int x = (int) ev.getX(); 380280bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan int y = (int) ev.getY(); 380380bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan 380480bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan boolean validPosition = setSelectionFromPosition(x, y); 380580bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan if (!validPosition) { 380680bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan // return if the touch wasn't on an area of concern 380780bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan return; 380880bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan } 380980bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan 3810146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 3811146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3812146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project performLongClick(); 3813146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3814146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 38154484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doScroll(MotionEvent e1, MotionEvent e2, float deltaX, float deltaY) { 381695d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan cancelAnimation(); 38174f58287a1e02325337e39073a50bbb880094099fRoboErik if (mStartingScroll) { 38184f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollX = 0; 38194f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollY = 0; 38204f58287a1e02325337e39073a50bbb880094099fRoboErik mStartingScroll = false; 38214f58287a1e02325337e39073a50bbb880094099fRoboErik } 38226d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 38234f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollX += deltaX; 38244f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollY += deltaY; 38254f58287a1e02325337e39073a50bbb880094099fRoboErik int distanceX = (int) mInitialScrollX; 38264f58287a1e02325337e39073a50bbb880094099fRoboErik int distanceY = (int) mInitialScrollY; 3827146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3828146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we haven't figured out the predominant scroll direction yet, 3829146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // then do it now. 3830146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mTouchMode == TOUCH_MODE_DOWN) { 3831146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int absDistanceX = Math.abs(distanceX); 3832146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int absDistanceY = Math.abs(distanceY); 3833146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrollStartY = mViewStartY; 3834146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPreviousDirection = 0; 3835146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3836f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan if (absDistanceX > absDistanceY) { 3837146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_HSCROLL; 3838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = distanceX; 3839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initNextView(-mViewStartX); 3840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_VSCROLL; 3842146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3843146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 3844146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We are already scrolling horizontally, so check if we 3845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // changed the direction of scrolling so that the other week 3846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // is now visible. 3847146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = distanceX; 3848146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distanceX != 0) { 3849146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int direction = (distanceX > 0) ? 1 : -1; 3850146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (direction != mPreviousDirection) { 3851146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The user has switched the direction of scrolling 3852146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // so re-init the next view 3853146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initNextView(-mViewStartX); 3854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPreviousDirection = direction; 3855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3857146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_VSCROLL) != 0) { 3860146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mScrollStartY + distanceY; 3861433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 3862433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // If dragging while already at the end, do a glow 3863433ba924de1ac26b923e2beb061812012749e4f3Michael Chan final int pulledToY = (int) (mScrollStartY + deltaY); 3864433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (pulledToY < 0) { 3865433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop.onPull(deltaY / mViewHeight); 3866433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (!mEdgeEffectBottom.isFinished()) { 3867433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom.onRelease(); 3868433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 3869433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } else if (pulledToY > mMaxViewStartY) { 3870433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom.onPull(deltaY / mViewHeight); 3871433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (!mEdgeEffectTop.isFinished()) { 3872433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop.onRelease(); 3873433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 3874433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 3875433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 3876146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 3877146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 3878146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mViewStartY > mMaxViewStartY) { 3879146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mMaxViewStartY; 3880146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3881146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeFirstHour(); 3882146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3883146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3884146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = true; 3885146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3886d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan mSelectionMode = SELECTION_HIDDEN; 3887146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3888146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3889146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3890f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan private void cancelAnimation() { 3891f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan Animation in = mViewSwitcher.getInAnimation(); 3892f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan if (in != null) { 389395d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan // cancel() doesn't terminate cleanly. 389495d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan in.scaleCurrentDuration(0); 38956d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 3896f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan Animation out = mViewSwitcher.getOutAnimation(); 3897f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan if (out != null) { 389895d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan // cancel() doesn't terminate cleanly. 389995d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan out.scaleCurrentDuration(0); 3900f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan } 3901f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan } 3902f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan 3903f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan private void doFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 3904f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan cancelAnimation(); 39056d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 3906146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_HIDDEN; 3907146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mOnFlingCalled = true; 390890a68379c01137781249156742cfc9ba21684b83Michael Chan 390990a68379c01137781249156742cfc9ba21684b83Michael Chan if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 3910030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown // Horizontal fling. 391111638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // initNextView(deltaX); 391290a68379c01137781249156742cfc9ba21684b83Michael Chan mTouchMode = TOUCH_MODE_INITIAL_STATE; 391390a68379c01137781249156742cfc9ba21684b83Michael Chan if (DEBUG) Log.d(TAG, "doFling: velocityX " + velocityX); 391490a68379c01137781249156742cfc9ba21684b83Michael Chan int deltaX = (int) e2.getX() - (int) e1.getX(); 39152c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan switchViews(deltaX < 0, mViewStartX, mViewWidth, velocityX); 3916146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = 0; 3917146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3918146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3919146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 392090a68379c01137781249156742cfc9ba21684b83Michael Chan if ((mTouchMode & TOUCH_MODE_VSCROLL) == 0) { 392190a68379c01137781249156742cfc9ba21684b83Michael Chan if (DEBUG) Log.d(TAG, "doFling: no fling"); 392290a68379c01137781249156742cfc9ba21684b83Michael Chan return; 392390a68379c01137781249156742cfc9ba21684b83Michael Chan } 392490a68379c01137781249156742cfc9ba21684b83Michael Chan 3925030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown // Vertical fling. 392690a68379c01137781249156742cfc9ba21684b83Michael Chan mTouchMode = TOUCH_MODE_INITIAL_STATE; 3927030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown mViewStartX = 0; 3928030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown 39293f6328f579b05c02606572c777541b97aa04f9f3Michael Chan if (DEBUG) { 39303f6328f579b05c02606572c777541b97aa04f9f3Michael Chan Log.d(TAG, "doFling: mViewStartY" + mViewStartY + " velocityY " + velocityY); 39313f6328f579b05c02606572c777541b97aa04f9f3Michael Chan } 39323f6328f579b05c02606572c777541b97aa04f9f3Michael Chan 3933146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Continue scrolling vertically 39343f6328f579b05c02606572c777541b97aa04f9f3Michael Chan mScrolling = true; 39353f6328f579b05c02606572c777541b97aa04f9f3Michael Chan mScroller.fling(0 /* startX */, mViewStartY /* startY */, 0 /* velocityX */, 3936433ba924de1ac26b923e2beb061812012749e4f3Michael Chan (int) -velocityY, 0 /* minX */, 0 /* maxX */, 0 /* minY */, 3937433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mMaxViewStartY /* maxY */, OVERFLING_DISTANCE, OVERFLING_DISTANCE); 3938433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 3939433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // When flinging down, show a glow when it hits the end only if it 3940433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // wasn't started at the top 3941433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (velocityY > 0 && mViewStartY != 0) { 3942433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mCallEdgeEffectOnAbsorb = true; 3943433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 3944433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // When flinging up, show a glow when it hits the end only if it wasn't 3945433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // started at the bottom 3946433ba924de1ac26b923e2beb061812012749e4f3Michael Chan else if (velocityY < 0 && mViewStartY != mMaxViewStartY) { 3947433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mCallEdgeEffectOnAbsorb = true; 3948433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 3949ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.post(mContinueScroll); 3950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3951146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3952146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean initNextView(int deltaX) { 3953146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Change the view to the previous day or week 3954d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getNextView(); 3955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time date = view.mBaseDate; 3956146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.set(mBaseDate); 3957146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean switchForward; 3958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (deltaX > 0) { 3959146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay -= mNumDays; 3960146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = mSelectionDay - mNumDays; 3961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchForward = false; 3962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay += mNumDays; 3964146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectionDay = mSelectionDay + mNumDays; 3965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchForward = true; 3966146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.normalize(true /* ignore isDst */); 3968146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initView(view); 3969ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan view.layout(getLeft(), getTop(), getRight(), getBottom()); 3970146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.reloadEvents(); 3971146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return switchForward; 3972146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3973146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3974d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 3975d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public boolean onScaleBegin(ScaleGestureDetector detector) { 3976d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = false; 39772fda24534978f55711526dbde747aa50d68dec40RoboErik float gestureCenterInPixels = detector.getFocusY() - DAY_HEADER_HEIGHT - mAlldayHeight; 3978d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) / (mCellHeight + DAY_GAP); 3979d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3980d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = Math.max(MIN_Y_SPAN, Math.abs(detector.getCurrentSpanY())); 3981d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = mCellHeight; 3982d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 39839ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG_SCALING) { 3984d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float ViewStartHour = mViewStartY / (float) (mCellHeight + DAY_GAP); 39856f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan Log.d(TAG, "onScaleBegin: mGestureCenterHour:" + mGestureCenterHour 39866f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan + "\tViewStartHour: " + ViewStartHour + "\tmViewStartY:" + mViewStartY 39876f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan + "\tmCellHeight:" + mCellHeight + " SpanY:" + detector.getCurrentSpanY()); 3988d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3989d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3990d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 3991d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3992d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3993d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 3994d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public boolean onScale(ScaleGestureDetector detector) { 39956f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan float spanY = Math.max(MIN_Y_SPAN, Math.abs(detector.getCurrentSpanY())); 3996d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3997d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = (int) (mCellHeightBeforeScaleGesture * spanY / mStartingSpanY); 3998d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3999d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight < mMinCellHeight) { 4000d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // If mStartingSpanY is too small, even a small increase in the 4001d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // gesture can bump the mCellHeight beyond MAX_CELL_HEIGHT 40026f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan mStartingSpanY = spanY; 4003d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = mMinCellHeight; 4004d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = mMinCellHeight; 4005d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } else if (mCellHeight > MAX_CELL_HEIGHT) { 4006d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = spanY; 4007d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = MAX_CELL_HEIGHT; 4008d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = MAX_CELL_HEIGHT; 4009d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4010d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 40112fda24534978f55711526dbde747aa50d68dec40RoboErik int gestureCenterInPixels = (int) detector.getFocusY() - DAY_HEADER_HEIGHT - mAlldayHeight; 4012d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = (int) (mGestureCenterHour * (mCellHeight + DAY_GAP)) - gestureCenterInPixels; 4013d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mMaxViewStartY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP) - mGridAreaHeight; 4014d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 40159ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG_SCALING) { 4016d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float ViewStartHour = mViewStartY / (float) (mCellHeight + DAY_GAP); 40176f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan Log.d(TAG, "onScale: mGestureCenterHour:" + mGestureCenterHour + "\tViewStartHour: " 4018d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + ViewStartHour + "\tmViewStartY:" + mViewStartY + "\tmCellHeight:" 4019d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + mCellHeight + " SpanY:" + detector.getCurrentSpanY()); 4020d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4021d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4022d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mViewStartY < 0) { 4023d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = 0; 4024d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) 4025d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan / (float) (mCellHeight + DAY_GAP); 4026d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } else if (mViewStartY > mMaxViewStartY) { 4027d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = mMaxViewStartY; 4028d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) 4029d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan / (float) (mCellHeight + DAY_GAP); 4030d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4031d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan computeFirstHour(); 4032d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4033d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mRemeasure = true; 4034d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan invalidate(); 4035d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 4036d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4037d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4038d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 4039d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public void onScaleEnd(ScaleGestureDetector detector) { 40404f58287a1e02325337e39073a50bbb880094099fRoboErik mScrollStartY = mViewStartY; 40414f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollY = 0; 40424f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollX = 0; 4043d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = 0; 4044d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4045d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4046146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 4047146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onTouchEvent(MotionEvent ev) { 4048146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int action = ev.getAction(); 40499ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "" + action + " ev.getPointerCount() = " + ev.getPointerCount()); 4050146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 40511ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan if ((mTouchMode & TOUCH_MODE_HSCROLL) == 0) { 40521ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan mScaleGestureDetector.onTouchEvent(ev); 40531ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan if (mScaleGestureDetector.isInProgress()) { 40541ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan return true; 40551ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan } 4056d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4057d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4058146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (action) { 405946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_DOWN: 40604f58287a1e02325337e39073a50bbb880094099fRoboErik mStartingScroll = true; 40619ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) { 40629ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan Log.e(TAG, "ACTION_DOWN ev.getDownTime = " + ev.getDownTime() + " Cnt=" 40639ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan + ev.getPointerCount()); 40649ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 40659ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 40662fda24534978f55711526dbde747aa50d68dec40RoboErik int bottom = mAlldayHeight + DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 40672fda24534978f55711526dbde747aa50d68dec40RoboErik if (ev.getY() < bottom) { 40682fda24534978f55711526dbde747aa50d68dec40RoboErik mTouchStartedInAlldayArea = true; 40692fda24534978f55711526dbde747aa50d68dec40RoboErik } else { 40702fda24534978f55711526dbde747aa50d68dec40RoboErik mTouchStartedInAlldayArea = false; 40712fda24534978f55711526dbde747aa50d68dec40RoboErik } 4072d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = true; 407346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 4074d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 407546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 407646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_MOVE: 40779ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "ACTION_MOVE Cnt=" + ev.getPointerCount() + DayView.this); 407846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 4079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 408046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 408146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_UP: 40829ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "ACTION_UP Cnt=" + ev.getPointerCount() + mHandleActionUp); 4083433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop.onRelease(); 4084433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom.onRelease(); 40854f58287a1e02325337e39073a50bbb880094099fRoboErik mStartingScroll = false; 408646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 408746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (!mHandleActionUp) { 408846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mHandleActionUp = true; 408957756df22153a2c0155a4e743c8a658caa8ada33RoboErik mViewStartX = 0; 409057756df22153a2c0155a4e743c8a658caa8ada33RoboErik invalidate(); 40917abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project return true; 409246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 409346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mOnFlingCalled) { 409446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 409546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 409646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 409746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mTouchMode = TOUCH_MODE_INITIAL_STATE; 409846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (Math.abs(mViewStartX) > mHorizontalSnapBackThreshold) { 409946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // The user has gone beyond the threshold so switch views 410046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.d(TAG, "- horizontal scroll: switch views"); 41012c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan switchViews(mViewStartX > 0, mViewStartX, mViewWidth, 0); 410246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mViewStartX = 0; 410346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 410446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 410546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Not beyond the threshold so invalidate which will cause 410646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // the view to snap back. Also call recalc() to ensure 410746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // that we have the correct starting date and title. 410846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.d(TAG, "- horizontal scroll: snap back"); 410946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan recalc(); 411046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan invalidate(); 411146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mViewStartX = 0; 411246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 411346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 411446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 411546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // If we were scrolling, then reset the selected hour so that it 411646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // is visible. 411746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mScrolling) { 411846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = false; 411946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan resetSelectedHour(); 4120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 4121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 412246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 4123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 412446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // This case isn't expected to happen. 412546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_CANCEL: 412646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.e(TAG, "ACTION_CANCEL"); 412746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 4128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 4129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project resetSelectedHour(); 4130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 413146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 413246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan default: 41339ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "Not MotionEvent " + ev.toString()); 413446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mGestureDetector.onTouchEvent(ev)) { 413546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 413646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 413746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return super.onTouchEvent(ev); 4138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { 4142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project MenuItem item; 4143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the trackball is held down, then the context menu pops up and 414546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // we never get onKeyUp() for the long-press. So check for it here 4146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // and change the selection to the long-press state. 4147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode != SELECTION_LONGPRESS) { 4148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 4149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 4150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4152e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan final long startMillis = getSelectedTimeInMillis(); 4153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags = DateUtils.FORMAT_SHOW_TIME 4154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT 4155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_SHOW_WEEKDAY; 4156c5f92d7bdeb1950ace783cc022aa41a4b4f00cd6Erik final String title = Utils.formatDateRange(mContext, startMillis, startMillis, flags); 4157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project menu.setHeaderTitle(title); 4158e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numSelectedEvents = mSelectedEvents.size(); 4160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 1) { 4161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Day view. 4162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is a selected event, then allow it to be viewed and 4164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // edited. 4165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (numSelectedEvents >= 1) { 41664484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_VIEW, 0, R.string.event_view); 4167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_info_details); 4169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4170ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan int accessLevel = getEventAccessLevel(mContext, mSelectedEvent); 4171a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel == ACCESS_LEVEL_EDIT) { 41724484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_EDIT, 0, R.string.event_edit); 4173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_edit); 4175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('e'); 4176a505627659f6bfba8869eac8089f7030f2d0d92cErik } 4177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4178a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel >= ACCESS_LEVEL_DELETE) { 41794484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_DELETE, 0, R.string.event_delete); 4180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_delete); 4182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 41844484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 4185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_add); 4187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('n'); 4188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Otherwise, if the user long-pressed on a blank hour, allow 419046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // them to create an event. They can also do this by tapping. 41914484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 4192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_add); 4194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('n'); 4195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Week view. 4198e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is a selected event, then allow it to be viewed and 4200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // edited. 4201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (numSelectedEvents >= 1) { 42024484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_VIEW, 0, R.string.event_view); 4203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_info_details); 4205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4206ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan int accessLevel = getEventAccessLevel(mContext, mSelectedEvent); 4207a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel == ACCESS_LEVEL_EDIT) { 42084484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_EDIT, 0, R.string.event_edit); 4209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_edit); 4211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('e'); 4212a505627659f6bfba8869eac8089f7030f2d0d92cErik } 4213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4214a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel >= ACCESS_LEVEL_DELETE) { 42154484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_DELETE, 0, R.string.event_delete); 4216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_delete); 4218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 42194484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan } 4220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 42214484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 42224484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 42234484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_add); 42244484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('n'); 4225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 42264484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_DAY, 0, R.string.show_day_view); 42274484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 42284484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_day); 42294484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('d'); 4230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 4233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private class ContextMenuHandler implements MenuItem.OnMenuItemClickListener { 4236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onMenuItemClick(MenuItem item) { 4237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (item.getItemId()) { 42384484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_VIEW: { 4239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 4240a7694eead7cbb293990bc89c3906e17bad36194cErik mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT_DETAILS, 42419e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.id, mSelectedEvent.startMillis, 424287f993ff96172f508d3f241f8a425f953c7eb739RoboErik mSelectedEvent.endMillis, 0, 0, -1); 4243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 42464484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_EDIT: { 4247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 42489e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.EDIT_EVENT, 42499e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.id, mSelectedEvent.startMillis, 425087f993ff96172f508d3f241f8a425f953c7eb739RoboErik mSelectedEvent.endMillis, 0, 0, -1); 4251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 42544484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_DAY: { 4255487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mController.sendEvent(this, EventType.GO_TO, getSelectedTime(), null, -1, 42569e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan ViewType.DAY); 4257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 42594484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_AGENDA: { 4260487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mController.sendEvent(this, EventType.GO_TO, getSelectedTime(), null, -1, 42619e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan ViewType.AGENDA); 4262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 42644484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_CREATE: { 4265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 4266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 42679e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 426887f993ff96172f508d3f241f8a425f953c7eb739RoboErik startMillis, endMillis, 0, 0, -1); 4269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 42714484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_DELETE: { 4272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 4273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 4274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long begin = selectedEvent.startMillis; 4275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long end = selectedEvent.endMillis; 4276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long id = selectedEvent.id; 42779e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.DELETE_EVENT, id, begin, 427887f993ff96172f508d3f241f8a425f953c7eb739RoboErik end, 0, 0, -1); 4279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project default: { 4283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return false; 4284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 4287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4290a505627659f6bfba8869eac8089f7030f2d0d92cErik private static int getEventAccessLevel(Context context, Event e) { 4291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ContentResolver cr = context.getContentResolver(); 4292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4293ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik int accessLevel = Calendars.CAL_ACCESS_NONE; 4294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Get the calendar id for this event 4296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Cursor cursor = cr.query(ContentUris.withAppendedId(Events.CONTENT_URI, e.id), 4297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project new String[] { Events.CALENDAR_ID }, 4298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* selection */, 4299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* selectionArgs */, 4300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* sort */); 4301e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4302e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan if (cursor == null) { 4303a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 4304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4305e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4306e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan if (cursor.getCount() == 0) { 4307e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan cursor.close(); 4308a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 4309e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan } 4310e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.moveToFirst(); 4312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long calId = cursor.getLong(0); 4313697bd6a8cec36cc75c72603674e57e4c6fe42dbfKen Shirriff cursor.close(); 4314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Uri uri = Calendars.CONTENT_URI; 4316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String where = String.format(CALENDARS_WHERE, calId); 4317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor = cr.query(uri, CALENDARS_PROJECTION, where, null, null); 4318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 43196d34cec523930368976bc8d358d0a6de1da3462cMichael Chan String calendarOwnerAccount = null; 4320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (cursor != null) { 4321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.moveToFirst(); 4322ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan accessLevel = cursor.getInt(CALENDARS_INDEX_ACCESS_LEVEL); 43236d34cec523930368976bc8d358d0a6de1da3462cMichael Chan calendarOwnerAccount = cursor.getString(CALENDARS_INDEX_OWNER_ACCOUNT); 4324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.close(); 4325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4326e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4327ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik if (accessLevel < Calendars.CAL_ACCESS_CONTRIBUTOR) { 4328a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 43296d34cec523930368976bc8d358d0a6de1da3462cMichael Chan } 4330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 43316d34cec523930368976bc8d358d0a6de1da3462cMichael Chan if (e.guestsCanModify) { 4332a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_EDIT; 4333a505627659f6bfba8869eac8089f7030f2d0d92cErik } 4334a505627659f6bfba8869eac8089f7030f2d0d92cErik 433546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (!TextUtils.isEmpty(calendarOwnerAccount) 433646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan && calendarOwnerAccount.equalsIgnoreCase(e.organizer)) { 4337a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_EDIT; 4338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4340a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_DELETE; 4341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 4344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Sets mSelectionDay and mSelectionHour based on the (x,y) touch position. 4345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * If the touch position is not within the displayed grid, then this 4346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * method returns false. 4347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 4348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param x the x position of the touch 4349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param y the y position of the touch 4350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return true if the touch position is valid 4351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 4352360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan private boolean setSelectionFromPosition(int x, final int y) { 4353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (x < mHoursWidth) { 4354360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan x = mHoursWidth; 4355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int day = (x - mHoursWidth) / (mCellWidth + DAY_GAP); 4358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (day >= mNumDays) { 4359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project day = mNumDays - 1; 4360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project day += mFirstJulianDay; 4362360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan mSelectionDay = day; 4363360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan 4364360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan if (y < DAY_HEADER_HEIGHT) { 4365aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan sendAccessibilityEventAsNeeded(false); 4366360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan return false; 4367360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan } 436846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 436946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectionHour = mFirstHour; /* First fully visible hour */ 437046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 437146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (y < mFirstCell) { 43722fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = true; 4373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 437446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // y is now offset from top of the scrollable region 437555a26d7062d5aa1a1b001b7271bb137276ab807eErik int adjustedY = y - mFirstCell; 437646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 437755a26d7062d5aa1a1b001b7271bb137276ab807eErik if (adjustedY < mFirstHourOffset) { 437846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan --mSelectionHour; /* In the partially visible hour */ 437946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 438055a26d7062d5aa1a1b001b7271bb137276ab807eErik mSelectionHour += (adjustedY - mFirstHourOffset) / (mCellHeight + HOUR_GAP); 438146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 438246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 43832fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = false; 4384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4385360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan 4386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project findSelectedEvent(x, y); 438746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 438846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// Log.i("Cal", "setSelectionFromPosition( " + x + ", " + y + " ) day: " + day + " hour: " 438946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// + mSelectionHour + " mFirstCell: " + mFirstCell + " mFirstHourOffset: " 439046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// + mFirstHourOffset); 4391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// if (mSelectedEvent != null) { 439246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// Log.i("Cal", " num events: " + mSelectedEvents.size() + " event: " 439346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// + mSelectedEvent.title); 4394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// for (Event ev : mSelectedEvents) { 4395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL 4396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 439746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// String timeRange = formatDateRange(mContext, ev.startMillis, ev.endMillis, flags); 4398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// 4399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", " " + timeRange + " " + ev.title); 4400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// } 4401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// } 4402aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan sendAccessibilityEventAsNeeded(true); 4403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 4404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void findSelectedEvent(int x, int y) { 4407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int date = mSelectionDay; 4408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellWidth = mCellWidth; 4409b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik ArrayList<Event> events = mEvents; 4410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 4411e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int left = computeDayLeftPosition(mSelectionDay - mFirstJulianDay); 4412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int top = 0; 4413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = null; 4414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 44162fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSelectionAllday) { 4417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float yDistance; 441846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan float minYdistance = 10000.0f; // any large number 4419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event closestEvent = null; 44202fda24534978f55711526dbde747aa50d68dec40RoboErik float drawHeight = mAlldayHeight; 44213eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int yOffset = DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 44222fda24534978f55711526dbde747aa50d68dec40RoboErik int maxUnexpandedColumn = mMaxUnexpandedAlldayEventCount; 44232fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount) { 44242fda24534978f55711526dbde747aa50d68dec40RoboErik // Leave a gap for the 'box +n' text 44252fda24534978f55711526dbde747aa50d68dec40RoboErik maxUnexpandedColumn--; 44262fda24534978f55711526dbde747aa50d68dec40RoboErik } 4427b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik events = mAllDayEvents; 4428b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik numEvents = events.size(); 4429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 4430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 44312fda24534978f55711526dbde747aa50d68dec40RoboErik if (!event.drawAsAllday() || 44322fda24534978f55711526dbde747aa50d68dec40RoboErik (!mShowAllAllDayEvents && event.getColumn() >= maxUnexpandedColumn)) { 44332fda24534978f55711526dbde747aa50d68dec40RoboErik // Don't check non-allday events or events that aren't shown 4434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 4435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.startDay <= mSelectionDay && event.endDay >= mSelectionDay) { 4438b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik float numRectangles = mShowAllAllDayEvents ? mMaxAlldayEvents 4439b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik : mMaxUnexpandedAlldayEventCount; 4440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float height = drawHeight / numRectangles; 4441f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan if (height > MAX_HEIGHT_OF_ONE_ALLDAY_EVENT) { 4442f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan height = MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 4443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float eventTop = yOffset + height * event.getColumn(); 4445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float eventBottom = eventTop + height; 4446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (eventTop < y && eventBottom > y) { 4447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the touch is inside the event rectangle, then 4448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // add the event. 4449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 4450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = event; 4451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4453146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Find the closest event 4454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (eventTop >= y) { 4455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project yDistance = eventTop - y; 4456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project yDistance = y - eventBottom; 4458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (yDistance < minYdistance) { 4460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project minYdistance = yDistance; 4461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = event; 4462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = closestEvent; 4467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 4468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Adjust y for the scrollable bitmap 4471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += mViewStartY - mFirstCell; 4472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use a region around (x,y) for the selection region 4474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect region = mRect; 4475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.left = x - 10; 4476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.right = x + 10; 4477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.top = y - 10; 4478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.bottom = y + 10; 4479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project EventGeometry geometry = mEventGeometry; 4481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 4483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 4484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the event rectangle. 4485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!geometry.computeEventRect(date, left, top, cellWidth, event)) { 4486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 4487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the event intersects the selection region, then add it to 4490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // mSelectedEvents. 4491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (geometry.eventIntersectsSelection(event, region)) { 4492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 4493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there are any events in the selected region, then assign the 4497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // closest one to mSelectedEvent. 4498146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvents.size() > 0) { 4499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 4500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event closestEvent = null; 450146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan float minDist = mViewWidth + mViewHeight; // some large distance 4502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int index = 0; index < len; index++) { 4503146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(index); 4504146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float dist = geometry.pointToEvent(x, y, ev); 4505146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (dist < minDist) { 4506146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project minDist = dist; 4507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = ev; 4508146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvent = closestEvent; 4511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4512146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Keep the selected hour and day consistent with the selected 451346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // event. They could be different if we touched on an empty hour 451446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // slot very close to an event in the previous hour slot. In 4515146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // that case we will select the nearby event. 4516146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startDay = mSelectedEvent.startDay; 4517146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endDay = mSelectedEvent.endDay; 4518146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionDay < startDay) { 4519146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = startDay; 4520146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionDay > endDay) { 4521146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionDay = endDay; 4522146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4523146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4524146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startHour = mSelectedEvent.startTime / 60; 4525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endHour; 4526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent.startTime < mSelectedEvent.endTime) { 4527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endHour = (mSelectedEvent.endTime - 1) / 60; 4528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endHour = mSelectedEvent.endTime / 60; 4530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4532349dd91e8475a72eb68a5eae4482ce7e82c01d16RoboErik if (mSelectionHour < startHour && mSelectionDay == startDay) { 4533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = startHour; 4534349dd91e8475a72eb68a5eae4482ce7e82c01d16RoboErik } else if (mSelectionHour > endHour && mSelectionDay == endDay) { 4535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionHour = endHour; 4536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Encapsulates the code to continue the scrolling after the 454146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // finger is lifted. Instead of stopping the scroll immediately, 4542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the scroll continues to "free spin" and gradually slows down. 4543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private class ContinueScroll implements Runnable { 4544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 45453f6328f579b05c02606572c777541b97aa04f9f3Michael Chan mScrolling = mScrolling && mScroller.computeScrollOffset(); 4546ea3f117db073ae796453479d00e9c7664d4471c5RoboErik if (!mScrolling || mPaused) { 45473f6328f579b05c02606572c777541b97aa04f9f3Michael Chan resetSelectedHour(); 45483f6328f579b05c02606572c777541b97aa04f9f3Michael Chan invalidate(); 45493f6328f579b05c02606572c777541b97aa04f9f3Michael Chan return; 4550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 45523f6328f579b05c02606572c777541b97aa04f9f3Michael Chan mViewStartY = mScroller.getCurrY(); 4553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4554433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mCallEdgeEffectOnAbsorb) { 4555433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mViewStartY < 0) { 4556433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop.onAbsorb((int) mLastVelocity); 4557433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mCallEdgeEffectOnAbsorb = false; 4558433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } else if (mViewStartY > mMaxViewStartY) { 4559433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom.onAbsorb((int) mLastVelocity); 4560433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mCallEdgeEffectOnAbsorb = false; 4561433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4562433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mLastVelocity = mScroller.getCurrVelocity(); 4563433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4564433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 4565433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mScrollStartY == 0 || mScrollStartY == mMaxViewStartY) { 4566433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // Allow overscroll/springback only on a fling, 4567433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // not a pull/fling from the end 4568433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mViewStartY < 0) { 4569433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mViewStartY = 0; 4570433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } else if (mViewStartY > mMaxViewStartY) { 4571433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mViewStartY = mMaxViewStartY; 4572433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeFirstHour(); 4576ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.post(this); 4577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 4578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 4582bd0e834aea317236d574f8738fe11a51fdc87968Erik * Cleanup the pop-up and timers. 4583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 4584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void cleanup() { 4585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against null-pointer exceptions 4586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPopup != null) { 4587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 4588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4589ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mPaused = true; 4590666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 459158f5055e1f3740382b4507e6eb88eebc2d6c21c1Michael Chan if (mHandler != null) { 459258f5055e1f3740382b4507e6eb88eebc2d6c21c1Michael Chan mHandler.removeCallbacks(mDismissPopup); 459358f5055e1f3740382b4507e6eb88eebc2d6c21c1Michael Chan mHandler.removeCallbacks(mUpdateCurrentTime); 4594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4595e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4596d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Utils.setSharedPreference(mContext, GeneralPreferences.KEY_DEFAULT_CELL_HEIGHT, 4597d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight); 4598d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 45997abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project // Turn off redraw 46007abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project mRemeasure = false; 4601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4603bd0e834aea317236d574f8738fe11a51fdc87968Erik /** 4604bd0e834aea317236d574f8738fe11a51fdc87968Erik * Restart the update timer 4605bd0e834aea317236d574f8738fe11a51fdc87968Erik */ 4606bd0e834aea317236d574f8738fe11a51fdc87968Erik public void restartCurrentTimeUpdates() { 4607ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mPaused = false; 4608ea3f117db073ae796453479d00e9c7664d4471c5RoboErik if (mHandler != null) { 46095d740e1320ba48ba66b72430f9896ab7d481fb54Michael Chan mHandler.removeCallbacks(mUpdateCurrentTime); 4610ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.post(mUpdateCurrentTime); 4611ea3f117db073ae796453479d00e9c7664d4471c5RoboErik } 4612bd0e834aea317236d574f8738fe11a51fdc87968Erik } 4613bd0e834aea317236d574f8738fe11a51fdc87968Erik 461446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 461546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan protected void onDetachedFromWindow() { 4616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cleanup(); 4617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project super.onDetachedFromWindow(); 4618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project class DismissPopup implements Runnable { 4621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 4622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against null-pointer exceptions 4623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPopup != null) { 4624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 4625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4628bd0e834aea317236d574f8738fe11a51fdc87968Erik 4629bd0e834aea317236d574f8738fe11a51fdc87968Erik class UpdateCurrentTime implements Runnable { 4630bd0e834aea317236d574f8738fe11a51fdc87968Erik public void run() { 4631bd0e834aea317236d574f8738fe11a51fdc87968Erik long currentTime = System.currentTimeMillis(); 4632bd0e834aea317236d574f8738fe11a51fdc87968Erik mCurrentTime.set(currentTime); 4633bd0e834aea317236d574f8738fe11a51fdc87968Erik //% causes update to occur on 5 minute marks (11:10, 11:15, 11:20, etc.) 46345d740e1320ba48ba66b72430f9896ab7d481fb54Michael Chan if (!DayView.this.mPaused) { 4635ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.postDelayed(mUpdateCurrentTime, UPDATE_CURRENT_TIME_DELAY 4636ea3f117db073ae796453479d00e9c7664d4471c5RoboErik - (currentTime % UPDATE_CURRENT_TIME_DELAY)); 46375d740e1320ba48ba66b72430f9896ab7d481fb54Michael Chan } 4638bd0e834aea317236d574f8738fe11a51fdc87968Erik mTodayJulianDay = Time.getJulianDay(currentTime, mCurrentTime.gmtoff); 4639bd0e834aea317236d574f8738fe11a51fdc87968Erik invalidate(); 4640bd0e834aea317236d574f8738fe11a51fdc87968Erik } 4641bd0e834aea317236d574f8738fe11a51fdc87968Erik } 4642ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 4643ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener { 4644ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 4645ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onSingleTapUp(MotionEvent ev) { 46469ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "GestureDetector.onSingleTapUp"); 4647d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doSingleTapUp(ev); 4648ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 4649ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4650ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 4651ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 4652ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public void onLongPress(MotionEvent ev) { 46539ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "GestureDetector.onLongPress"); 4654d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doLongPress(ev); 4655ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4656ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 4657ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 4658ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 46599ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "GestureDetector.onScroll"); 46602fda24534978f55711526dbde747aa50d68dec40RoboErik if (mTouchStartedInAlldayArea) { 46610e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik if (Math.abs(distanceX) < Math.abs(distanceY)) { 46620e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik return false; 46630e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik } 46640e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik // don't scroll vertically if this started in the allday area 46650e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik distanceY = 0; 46662fda24534978f55711526dbde747aa50d68dec40RoboErik } 4667d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doScroll(e1, e2, distanceX, distanceY); 4668ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 4669ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4670ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 4671ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 4672ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 46739ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "GestureDetector.onFling"); 46749ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 46752fda24534978f55711526dbde747aa50d68dec40RoboErik if (mTouchStartedInAlldayArea) { 46760e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik if (Math.abs(velocityX) < Math.abs(velocityY)) { 46770e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik return false; 46780e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik } 46790e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik // don't fling vertically if this started in the allday area 46800e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik velocityY = 0; 46812fda24534978f55711526dbde747aa50d68dec40RoboErik } 4682d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doFling(e1, e2, velocityX, velocityY); 4683ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 4684ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4685ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 4686ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 4687ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onDown(MotionEvent ev) { 46889ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "GestureDetector.onDown"); 4689d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doDown(ev); 4690ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 4691ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4692ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4693cd405a28e6821b116dcf3c531805d0c90b6cc08cErik 4694cd405a28e6821b116dcf3c531805d0c90b6cc08cErik @Override 4695cd405a28e6821b116dcf3c531805d0c90b6cc08cErik public boolean onLongClick(View v) { 469643e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik int flags = DateUtils.FORMAT_SHOW_WEEKDAY; 469743e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik long time = getSelectedTimeInMillis(); 469843e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik if (!mSelectionAllday) { 469943e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik flags |= DateUtils.FORMAT_SHOW_TIME; 470043e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik } 470143e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik if (DateFormat.is24HourFormat(mContext)) { 470243e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik flags |= DateUtils.FORMAT_24HOUR; 470343e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik } 470443e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik mLongPressTitle = Utils.formatDateRange(mContext, time, time, flags); 470520b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik new AlertDialog.Builder(mContext).setTitle(mLongPressTitle) 470620b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik .setItems(mLongPressItems, new DialogInterface.OnClickListener() { 470720b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik @Override 470820b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik public void onClick(DialogInterface dialog, int which) { 470920b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik if (which == 0) { 4710edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan long extraLong = 0; 4711edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan if (mSelectionAllday) { 4712edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan extraLong = CalendarController.EXTRA_CREATE_ALL_DAY; 4713edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan } 4714edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan mController.sendEventRelatedEventWithExtra(this, 4715edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan EventType.CREATE_EVENT, -1, getSelectedTimeInMillis(), 0, -1, 4716edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan -1, extraLong, -1); 471720b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik } 471820b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik } 471973bb3ae73b067e7c926d3ac660d059b2a06309b2RoboErik }).show().setCanceledOnTouchOutside(true); 4720cd405a28e6821b116dcf3c531805d0c90b6cc08cErik return true; 4721cd405a28e6821b116dcf3c531805d0c90b6cc08cErik } 47222c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 47232c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan // The rest of this file was borrowed from Launcher2 - PagedView.java 47242c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan private static final int MINIMUM_SNAP_VELOCITY = 2200; 47252c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 472695d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan private class ScrollInterpolator implements Interpolator { 47272c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan public ScrollInterpolator() { 47282c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 47292c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 47302c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan public float getInterpolation(float t) { 47312c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan t -= 1.0f; 473295d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan t = t * t * t * t * t + 1; 473395d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan 473495d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan if ((1 - t) * mAnimationDistance < 1) { 473595d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan cancelAnimation(); 473695d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan } 473795d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan 473895d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan return t; 47392c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 47402c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 47412c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 47422c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan private long calculateDuration(float delta, float width, float velocity) { 47432c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan /* 47442c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * Here we compute a "distance" that will be used in the computation of 47452c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * the overall snap duration. This is a function of the actual distance 47462c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * that needs to be traveled; we keep this value close to half screen 47472c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * size in order to reduce the variance in snap duration as a function 47482c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * of the distance the page needs to travel. 47492c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan */ 47502c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan final float halfScreenSize = width / 2; 47512c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan float distanceRatio = delta / width; 47522c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan float distanceInfluenceForSnapDuration = distanceInfluenceForSnapDuration(distanceRatio); 47532c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan float distance = halfScreenSize + halfScreenSize * distanceInfluenceForSnapDuration; 47542c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 47552c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan velocity = Math.abs(velocity); 47562c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan velocity = Math.max(MINIMUM_SNAP_VELOCITY, velocity); 47572c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 47582c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan /* 47592c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * we want the page's snap velocity to approximately match the velocity 47602c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * at which the user flings, so we scale the duration by a value near to 47612c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * the derivative of the scroll interpolator at zero, ie. 5. We use 6 to 47622c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * make it a little slower. 47632c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan */ 47642c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan long duration = 6 * Math.round(1000 * Math.abs(distance / velocity)); 47652c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan if (DEBUG) { 47662c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan Log.e(TAG, "halfScreenSize:" + halfScreenSize + " delta:" + delta + " distanceRatio:" 47672c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan + distanceRatio + " distance:" + distance + " velocity:" + velocity 47682c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan + " duration:" + duration + " distanceInfluenceForSnapDuration:" 47692c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan + distanceInfluenceForSnapDuration); 47702c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 47712c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan return duration; 47722c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 47732c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 47742c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan /* 47752c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * We want the duration of the page snap animation to be influenced by the 47762c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * distance that the screen has to travel, however, we don't want this 47772c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * duration to be effected in a purely linear fashion. Instead, we use this 47782c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * method to moderate the effect that the distance of travel has on the 47792c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * overall snap duration. 47802c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan */ 47812c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan private float distanceInfluenceForSnapDuration(float f) { 47822c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan f -= 0.5f; // center the values about 0. 47832c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan f *= 0.3f * Math.PI / 2.0f; 47842c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan return (float) Math.sin(f); 47852c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 4786146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project} 4787