DayView.java revision b85452b2589be5f057a2d4bd8991c7c7c740752a
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 1946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.Animator; 2046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.AnimatorListenerAdapter; 2146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.ObjectAnimator; 2246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.animation.ValueAnimator; 2320b6fb580bf09dbd610a256ffd3165c03053cb70RoboErikimport android.app.AlertDialog; 249ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chanimport android.app.Service; 25146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.ContentResolver; 26146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.ContentUris; 27146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context; 2820b6fb580bf09dbd610a256ffd3165c03053cb70RoboErikimport android.content.DialogInterface; 29146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.res.Resources; 30146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.res.TypedArray; 31146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.database.Cursor; 32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Canvas; 33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Paint; 34e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErikimport android.graphics.Paint.Align; 35dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.graphics.Paint.Style; 36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Rect; 37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.graphics.Typeface; 38c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawaimport android.graphics.drawable.Drawable; 39146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.net.Uri; 40146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.os.Handler; 41a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees; 42a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Calendars; 43a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Events; 443e7015267340b09d142dfcd3ff8acda257711023Shachar Shemeshimport android.text.Layout.Alignment; 45e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErikimport android.text.SpannableStringBuilder; 46f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chanimport android.text.StaticLayout; 473e7015267340b09d142dfcd3ff8acda257711023Shachar Shemeshimport android.text.TextPaint; 48f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chanimport android.text.TextUtils; 49146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateFormat; 50146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateUtils; 51146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time; 52e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErikimport android.text.style.StyleSpan; 53146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.util.Log; 54146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ContextMenu; 55dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.view.ContextMenu.ContextMenuInfo; 56ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.GestureDetector; 57146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.Gravity; 58146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.KeyEvent; 59146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.LayoutInflater; 60146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.MenuItem; 61146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.MotionEvent; 62d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chanimport android.view.ScaleGestureDetector; 63146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.View; 64146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewConfiguration; 65146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewGroup; 66146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.WindowManager; 67259b8f9a21fffd3858218581e9daaf689b6b888fErikimport android.view.accessibility.AccessibilityEvent; 689ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chanimport android.view.accessibility.AccessibilityManager; 6946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chanimport android.view.animation.AccelerateDecelerateInterpolator; 70ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.animation.Animation; 712c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chanimport android.view.animation.Interpolator; 72ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.view.animation.TranslateAnimation; 73433ba924de1ac26b923e2beb061812012749e4f3Michael Chanimport android.widget.EdgeEffect; 74146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.ImageView; 753f6328f579b05c02606572c777541b97aa04f9f3Michael Chanimport android.widget.OverScroller; 76146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.PopupWindow; 77146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.TextView; 78ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chanimport android.widget.ViewSwitcher; 79146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 809e196e46b238e6bca1ef86c7d673807b78ab7016Michael Chanimport com.android.calendar.CalendarController.EventType; 819e196e46b238e6bca1ef86c7d673807b78ab7016Michael Chanimport com.android.calendar.CalendarController.ViewType; 829e196e46b238e6bca1ef86c7d673807b78ab7016Michael Chan 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; 1100a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson // duration for events' cross-fade animation 1110a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson private static final int EVENTS_CROSS_FADE_DURATION = 400; 112ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson // duration to show the event clicked 11331c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson private static final int CLICK_DISPLAY_DURATION = 50; 114705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 1154484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_AGENDA = 2; 1164484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_DAY = 3; 1174484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_VIEW = 5; 1184484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_CREATE = 6; 1194484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_EDIT = 7; 1204484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private static final int MENU_EVENT_DELETE = 8; 1214484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan 12211ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan private static int DEFAULT_CELL_HEIGHT = 64; 123d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int MAX_CELL_HEIGHT = 150; 124d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int MIN_Y_SPAN = 100; 125d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mOnFlingCalled; 1274f58287a1e02325337e39073a50bbb880094099fRoboErik private boolean mStartingScroll = false; 128ea3f117db073ae796453479d00e9c7664d4471c5RoboErik protected boolean mPaused = true; 129ea3f117db073ae796453479d00e9c7664d4471c5RoboErik private Handler mHandler; 130666fc5e8ddbac15c951aad738bd818ee307eae42Erik /** 131666fc5e8ddbac15c951aad738bd818ee307eae42Erik * ID of the last event which was displayed with the toast popup. 132666fc5e8ddbac15c951aad738bd818ee307eae42Erik * 133666fc5e8ddbac15c951aad738bd818ee307eae42Erik * This is used to prevent popping up multiple quick views for the same event, especially 134666fc5e8ddbac15c951aad738bd818ee307eae42Erik * during calendar syncs. This becomes valid when an event is selected, either by default 135666fc5e8ddbac15c951aad738bd818ee307eae42Erik * on starting calendar or by scrolling to an event. It becomes invalid when the user 136666fc5e8ddbac15c951aad738bd818ee307eae42Erik * explicitly scrolls to an empty time slot, changes views, or deletes the event. 137666fc5e8ddbac15c951aad738bd818ee307eae42Erik */ 138666fc5e8ddbac15c951aad738bd818ee307eae42Erik private long mLastPopupEventID; 139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 140ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan protected Context mContext; 141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String[] CALENDARS_PROJECTION = new String[] { 143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Calendars._ID, // 0 144ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik Calendars.CALENDAR_ACCESS_LEVEL, // 1 1456d34cec523930368976bc8d358d0a6de1da3462cMichael Chan Calendars.OWNER_ACCOUNT, // 2 146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int CALENDARS_INDEX_ACCESS_LEVEL = 1; 1486d34cec523930368976bc8d358d0a6de1da3462cMichael Chan private static final int CALENDARS_INDEX_OWNER_ACCOUNT = 2; 149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final String CALENDARS_WHERE = Calendars._ID + "=%d"; 150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_NONE = 0; 152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_ABOVE = 1; 153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_BELOW = 2; 154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_LEFT = 4; 155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int FROM_RIGHT = 8; 156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 157a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_NONE = 0; 158a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_DELETE = 1; 159a505627659f6bfba8869eac8089f7030f2d0d92cErik private static final int ACCESS_LEVEL_EDIT = 2; 160a505627659f6bfba8869eac8089f7030f2d0d92cErik 161d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan private static int mHorizontalSnapBackThreshold = 128; 162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 163056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final ContinueScroll mContinueScroll = new ContinueScroll(); 164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Make this visible within the package for more informative debugging 166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time mBaseDate; 167bd0e834aea317236d574f8738fe11a51fdc87968Erik private Time mCurrentTime; 168bd0e834aea317236d574f8738fe11a51fdc87968Erik //Update the current time line every five minutes if the window is left open that long 169bd0e834aea317236d574f8738fe11a51fdc87968Erik private static final int UPDATE_CURRENT_TIME_DELAY = 300000; 170056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final UpdateCurrentTime mUpdateCurrentTime = new UpdateCurrentTime(); 171bd0e834aea317236d574f8738fe11a51fdc87968Erik private int mTodayJulianDay; 172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 173056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Typeface mBold = Typeface.DEFAULT_BOLD; 174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstJulianDay; 1751662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson private int mLoadedFirstJulianDay = -1; 176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mLastJulianDay; 177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMonthLength; 179487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstVisibleDate; 180487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstVisibleDayOfWeek; 181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int[] mEarliestStartHour; // indexed by the week day offset 182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean[] mHasAllDayEvent; // indexed by the week day offset 183259b8f9a21fffd3858218581e9daaf689b6b888fErik private String mEventCountTemplate; 184056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final CharSequence[] mLongPressItems; 18520b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik private String mLongPressTitle; 186056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private Event mClickedEvent; // The event the user clicked on 187ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson private Event mSavedClickedEvent; 188ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson private static int mOnDownDelay; 189056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private int mClickedYLocation; 19031c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson private long mDownTouchTime; 191056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson 1920a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson private int mEventsAlpha = 255; 1930a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson private ObjectAnimator mEventsCrossFadeAnimation; 194259b8f9a21fffd3858218581e9daaf689b6b888fErik 195259b8f9a21fffd3858218581e9daaf689b6b888fErik protected static StringBuilder mStringBuilder = new StringBuilder(50); 196259b8f9a21fffd3858218581e9daaf689b6b888fErik // TODO recreate formatter when locale changes 197259b8f9a21fffd3858218581e9daaf689b6b888fErik protected static Formatter mFormatter = new Formatter(mStringBuilder, Locale.getDefault()); 198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 199056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Runnable mTZUpdater = new Runnable() { 200731f1cb808b7586b93615b408ab2636081fab0dcErik @Override 201731f1cb808b7586b93615b408ab2636081fab0dcErik public void run() { 202731f1cb808b7586b93615b408ab2636081fab0dcErik String tz = Utils.getTimeZone(mContext, this); 203731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate.timezone = tz; 204731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate.normalize(true); 205731f1cb808b7586b93615b408ab2636081fab0dcErik mCurrentTime.switchTimezone(tz); 206731f1cb808b7586b93615b408ab2636081fab0dcErik invalidate(); 207731f1cb808b7586b93615b408ab2636081fab0dcErik } 208731f1cb808b7586b93615b408ab2636081fab0dcErik }; 209731f1cb808b7586b93615b408ab2636081fab0dcErik 210ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson // Sets the "clicked" color from the clicked event 211ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson private final Runnable mSetClick = new Runnable() { 212ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson @Override 213ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson public void run() { 214ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson mClickedEvent = mSavedClickedEvent; 215ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson mSavedClickedEvent = null; 216ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson DayView.this.invalidate(); 217ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson } 218ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson }; 219056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson 22031c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson // Clears the "clicked" color from the clicked event and launch the event 221056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Runnable mClearClick = new Runnable() { 222056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson @Override 223056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson public void run() { 22431c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson if (mClickedEvent != null) { 22531c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, mClickedEvent.id, 22631c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson mClickedEvent.startMillis, mClickedEvent.endMillis, 227b85452b2589be5f057a2d4bd8991c7c7c740752aIsaac Katzenelson DayView.this.getWidth() / 2, mClickedYLocation, 22831c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson getSelectedTimeInMillis()); 229056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson } 23031c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson mClickedEvent = null; 23131c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson DayView.this.invalidate(); 232056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson } 233056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson }; 234056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson 235056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final TodayAnimatorListener mTodayAnimatorListener = new TodayAnimatorListener(); 2365b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 2375b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik class TodayAnimatorListener extends AnimatorListenerAdapter { 2385b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private volatile Animator mAnimator = null; 2395b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private volatile boolean mFadingIn = false; 2405b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 2415b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik @Override 2425b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void onAnimationEnd(Animator animation) { 2435b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik synchronized (this) { 2445b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mAnimator != animation) { 2455b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik animation.removeAllListeners(); 2465b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik animation.cancel(); 2475b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik return; 2485b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2495b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mFadingIn) { 2505b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mTodayAnimator != null) { 2515b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.removeAllListeners(); 2525b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.cancel(); 2535b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2545b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator = ObjectAnimator 2555b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik .ofInt(DayView.this, "animateTodayAlpha", 255, 0); 2565b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimator = mTodayAnimator; 2575b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mFadingIn = false; 2585b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.addListener(this); 2595b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.setDuration(600); 2605b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.start(); 2615b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } else { 2625b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateToday = false; 2635b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateTodayAlpha = 0; 2645b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimator.removeAllListeners(); 2655b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimator = null; 2665b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator = null; 2675b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik invalidate(); 2685b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2695b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2705b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2715b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 2725b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void setAnimator(Animator animation) { 2735b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimator = animation; 2745b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2755b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 2765b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void setFadingIn(boolean fadingIn) { 2775b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mFadingIn = fadingIn; 2785b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2795b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 2805b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2815b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 28246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() { 28346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 28446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void onAnimationStart(Animator animation) { 28546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = true; 28646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 28746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 28846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 28946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void onAnimationCancel(Animator animation) { 29046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = false; 29146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 29246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 29346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 29446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void onAnimationEnd(Animator animation) { 29546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mScrolling = false; 29646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan resetSelectedHour(); 29746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan invalidate(); 29846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 29946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan }; 30046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * This variable helps to avoid unnecessarily reloading events by keeping 303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * track of the start millis parameter used for the most recent loading 304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * of events. If the next reload matches this, then the events are not 305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * reloaded. To force a reload, set this to zero (this is set to zero 306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * in the method clearCachedEvents()). 307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private long mLastReloadMillis; 309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private ArrayList<Event> mEvents = new ArrayList<Event>(); 31108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private ArrayList<Event> mAllDayEvents = new ArrayList<Event>(); 31208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout[] mLayouts = null; 31308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout[] mAllDayLayouts = null; 314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionDay; // Julian day 315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionHour; 316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3172fda24534978f55711526dbde747aa50d68dec40RoboErik boolean mSelectionAllday; 318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 319989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson // Current selection info for accessibility 320989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson private int mSelectionDayForAccessibility; // Julian day 321989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson private int mSelectionHourForAccessibility; 322989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson private Event mSelectedEventForAccessibility; 323989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson // Last selection info for accessibility 324989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson private int mLastSelectionDayForAccessibility; 325989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson private int mLastSelectionHourForAccessibility; 326989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson private Event mLastSelectedEventForAccessibility; 327989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson 3289ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 3293eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan /** Width of a day or non-conflicting event */ 330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mCellWidth; 331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pre-allocate these objects and re-use them 333056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Rect mRect = new Rect(); 334056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Rect mDestRect = new Rect(); 335056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Rect mSelectionRect = new Rect(); 3362fda24534978f55711526dbde747aa50d68dec40RoboErik // This encloses the more allDay events icon 337056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Rect mExpandAllDayRect = new Rect(); 338e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik // TODO Clean up paint usage 339056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Paint mPaint = new Paint(); 340056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Paint mEventTextPaint = new Paint(); 341056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Paint mSelectionPaint = new Paint(); 34202041687c35441e8a21cb763f1fc3a26525292efDavid Brown private float[] mLines; 343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 344487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan private int mFirstDayOfWeek; // First day of the week 345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private PopupWindow mPopup; 347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private View mPopupView; 348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The number of milliseconds to show the popup window 350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int POPUP_DISMISS_DELAY = 3000; 351056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final DismissPopup mDismissPopup = new DismissPopup(); 352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mRemeasure = true; 354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private final EventLoader mEventLoader; 356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected final EventGeometry mEventGeometry; 357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 358e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static float GRID_LINE_LEFT_MARGIN = 0; 359000ba1109e2f4e527e9227fe341598ceeb3fbca6Michael Chan private static final float GRID_LINE_INNER_WIDTH = 1; 3603eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int DAY_GAP = 1; 362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int HOUR_GAP = 1; 3632fda24534978f55711526dbde747aa50d68dec40RoboErik // This is the standard height of an allday event with no restrictions 3649c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan private static int SINGLE_ALLDAY_HEIGHT = 34; 3652fda24534978f55711526dbde747aa50d68dec40RoboErik /** 3662fda24534978f55711526dbde747aa50d68dec40RoboErik * This is the minimum desired height of a allday event. 3672fda24534978f55711526dbde747aa50d68dec40RoboErik * When unexpanded, allday events will use this height. 3682fda24534978f55711526dbde747aa50d68dec40RoboErik * When expanded allDay events will attempt to grow to fit all 3692fda24534978f55711526dbde747aa50d68dec40RoboErik * events at this height. 3702fda24534978f55711526dbde747aa50d68dec40RoboErik */ 3712fda24534978f55711526dbde747aa50d68dec40RoboErik private static float MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT = 28.0F; // in pixels 3722fda24534978f55711526dbde747aa50d68dec40RoboErik /** 3732fda24534978f55711526dbde747aa50d68dec40RoboErik * This is how big the unexpanded allday height is allowed to be. 3742fda24534978f55711526dbde747aa50d68dec40RoboErik * It will get adjusted based on screen size 3752fda24534978f55711526dbde747aa50d68dec40RoboErik */ 3762fda24534978f55711526dbde747aa50d68dec40RoboErik private static int MAX_UNEXPANDED_ALLDAY_HEIGHT = 3772fda24534978f55711526dbde747aa50d68dec40RoboErik (int) (MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT * 4); 3782fda24534978f55711526dbde747aa50d68dec40RoboErik /** 3792fda24534978f55711526dbde747aa50d68dec40RoboErik * This is the minimum size reserved for displaying regular events. 3802fda24534978f55711526dbde747aa50d68dec40RoboErik * The expanded allDay region can't expand into this. 3812fda24534978f55711526dbde747aa50d68dec40RoboErik */ 3822fda24534978f55711526dbde747aa50d68dec40RoboErik private static int MIN_HOURS_HEIGHT = 180; 38325996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private static int ALLDAY_TOP_MARGIN = 1; 3842fda24534978f55711526dbde747aa50d68dec40RoboErik // The largest a single allDay event will become. 385f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan private static int MAX_HEIGHT_OF_ONE_ALLDAY_EVENT = 34; 386e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3878f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int HOURS_TOP_MARGIN = 2; 388e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int HOURS_LEFT_MARGIN = 2; 3898f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int HOURS_RIGHT_MARGIN = 4; 3908f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int HOURS_MARGIN = HOURS_LEFT_MARGIN + HOURS_RIGHT_MARGIN; 39195f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan private static int NEW_EVENT_MARGIN = 4; 392462196d197de326006aaf15f8bb7a8d83b8e2a60Peter Ng private static int NEW_EVENT_WIDTH = 2; 39395f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan private static int NEW_EVENT_MAX_LENGTH = 16; 394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 395bd0e834aea317236d574f8738fe11a51fdc87968Erik private static int CURRENT_TIME_LINE_HEIGHT = 2; 396bd0e834aea317236d574f8738fe11a51fdc87968Erik private static int CURRENT_TIME_LINE_BORDER_WIDTH = 1; 397763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int CURRENT_TIME_LINE_SIDE_BUFFER = 4; 398763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int CURRENT_TIME_LINE_TOP_OFFSET = 2; 399bd0e834aea317236d574f8738fe11a51fdc87968Erik 400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MINUTES_PER_HOUR = 60; 401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MINUTES_PER_DAY = MINUTES_PER_HOUR * 24; 402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_MINUTE = 60 * 1000; 403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_HOUR = (3600 * 1000); 404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /* package */ static final int MILLIS_PER_DAY = MILLIS_PER_HOUR * 24; 405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4062fda24534978f55711526dbde747aa50d68dec40RoboErik // More events text will transition between invisible and this alpha 4072fda24534978f55711526dbde747aa50d68dec40RoboErik private static final int MORE_EVENTS_MAX_ALPHA = 0x4C; 408e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_ONE_DAY_LEFT_MARGIN = 0; 409e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_ONE_DAY_RIGHT_MARGIN = 5; 410e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_ONE_DAY_BOTTOM_MARGIN = 6; 411e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_LEFT_MARGIN = 5; 412e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_RIGHT_MARGIN = 4; 413e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int DAY_HEADER_BOTTOM_MARGIN = 3; 4143eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float DAY_HEADER_FONT_SIZE = 14; 4158f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static float DATE_HEADER_FONT_SIZE = 32; 4163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float NORMAL_FONT_SIZE = 12; 4173eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static float EVENT_TEXT_FONT_SIZE = 12; 418e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static float HOURS_TEXT_SIZE = 12; 419e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static float AMPM_TEXT_SIZE = 9; 4208f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int MIN_HOURS_WIDTH = 96; 421763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int MIN_CELL_WIDTH_FOR_TEXT = 20; 422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int MAX_EVENT_TEXT_LEN = 500; 4232fda24534978f55711526dbde747aa50d68dec40RoboErik // smallest height to draw an event with 42425996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private static float MIN_EVENT_HEIGHT = 24.0F; // in pixels 4251ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int CALENDAR_COLOR_SQUARE_SIZE = 10; 42625996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private static int EVENT_RECT_TOP_MARGIN = 1; 427763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int EVENT_RECT_BOTTOM_MARGIN = 0; 428763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int EVENT_RECT_LEFT_MARGIN = 1; 429763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik private static int EVENT_RECT_RIGHT_MARGIN = 0; 43025996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private static int EVENT_RECT_STROKE_WIDTH = 2; 4311ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_TEXT_TOP_MARGIN = 2; 43225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private static int EVENT_TEXT_BOTTOM_MARGIN = 2; 43395d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng private static int EVENT_TEXT_LEFT_MARGIN = 6; 43495d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng private static int EVENT_TEXT_RIGHT_MARGIN = 6; 435e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int ALL_DAY_EVENT_RECT_BOTTOM_MARGIN = 1; 4361ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_TOP_MARGIN = EVENT_TEXT_TOP_MARGIN; 4371ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN = EVENT_TEXT_BOTTOM_MARGIN; 4381ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_LEFT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 4391ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private static int EVENT_ALL_DAY_TEXT_RIGHT_MARGIN = EVENT_TEXT_RIGHT_MARGIN; 4402fda24534978f55711526dbde747aa50d68dec40RoboErik // margins and sizing for the expand allday icon 441cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik private static int EXPAND_ALL_DAY_BOTTOM_MARGIN = 10; 4422fda24534978f55711526dbde747aa50d68dec40RoboErik // sizing for "box +n" in allDay events 4432fda24534978f55711526dbde747aa50d68dec40RoboErik private static int EVENT_SQUARE_WIDTH = 10; 4442fda24534978f55711526dbde747aa50d68dec40RoboErik private static int EVENT_LINE_PADDING = 4; 445ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson private static int NEW_EVENT_HINT_FONT_SIZE = 12; 446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mPressedColor; 448056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private static int mClickedColor; 449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static int mEventTextColor; 4502fda24534978f55711526dbde747aa50d68dec40RoboErik private static int mMoreEventsTextColor; 451f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan 45264b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok private static int mWeek_saturdayColor; 45364b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok private static int mWeek_sundayColor; 454d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarDateBannerTextColor; 455d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan private static int mCalendarAmPmLabel; 456ba902466b19b11d587468e354edc58e542707747Michael Chan private static int mCalendarGridAreaSelected; 4573eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int mCalendarGridLineInnerHorizontalColor; 4583eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int mCalendarGridLineInnerVerticalColor; 45921bd42039c92232647f54461cd20708224cc7eb6Michael Chan private static int mFutureBgColor; 460cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan private static int mFutureBgColorRes; 461e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int mBgColor; 462ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson private static int mNewEventHintColor; 4638f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private static int mCalendarHourLabelColor; 4642fda24534978f55711526dbde747aa50d68dec40RoboErik private static int mMoreAlldayEventsTextAlpha = MORE_EVENTS_MAX_ALPHA; 465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 46695d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan private float mAnimationDistance = 0; 467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewStartX; 468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewStartY; 469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mMaxViewStartY; 470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewHeight; 471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mViewWidth; 47246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan private int mGridAreaHeight = -1; 473d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int mCellHeight = 0; // shared among all DayViews 474d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private static int mMinCellHeight = 32; 475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mScrollStartY; 476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mPreviousDirection; 477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 478d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** 479d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * Vertical distance or span between the two touch points at the start of a 480d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * scaling gesture 481d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan */ 482d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private float mStartingSpanY = 0; 483d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** Height of 1 hour in pixels at the start of a scaling gesture */ 484d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private int mCellHeightBeforeScaleGesture; 485d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** The hour at the center two touch points */ 486d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private float mGestureCenterHour = 0; 487d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan /** 488d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * Flag to decide whether to handle the up event. Cases where up events 489d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * should be ignored are 1) right after a scale gesture and 2) finger was 490d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan * down before app launch 491d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan */ 492d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan private boolean mHandleActionUp = true; 493d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mHoursTextHeight; 4952fda24534978f55711526dbde747aa50d68dec40RoboErik /** 4962fda24534978f55711526dbde747aa50d68dec40RoboErik * The height of the area used for allday events 4972fda24534978f55711526dbde747aa50d68dec40RoboErik */ 4982fda24534978f55711526dbde747aa50d68dec40RoboErik private int mAlldayHeight; 4992fda24534978f55711526dbde747aa50d68dec40RoboErik /** 5002fda24534978f55711526dbde747aa50d68dec40RoboErik * The height of the allday event area used during animation 5012fda24534978f55711526dbde747aa50d68dec40RoboErik */ 5022fda24534978f55711526dbde747aa50d68dec40RoboErik private int mAnimateDayHeight = 0; 5032fda24534978f55711526dbde747aa50d68dec40RoboErik /** 5042fda24534978f55711526dbde747aa50d68dec40RoboErik * The height of an individual allday event during animation 5052fda24534978f55711526dbde747aa50d68dec40RoboErik */ 5062fda24534978f55711526dbde747aa50d68dec40RoboErik private int mAnimateDayEventHeight = (int) MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT; 5072fda24534978f55711526dbde747aa50d68dec40RoboErik /** 508cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik * Whether to use the expand or collapse icon. 5092fda24534978f55711526dbde747aa50d68dec40RoboErik */ 51097326ee1ea9b1bb17e0e2bcfe344352d4bb03001RoboErik private static boolean mUseExpandIcon = true; 5112fda24534978f55711526dbde747aa50d68dec40RoboErik /** 5122fda24534978f55711526dbde747aa50d68dec40RoboErik * The height of the day names/numbers 5132fda24534978f55711526dbde747aa50d68dec40RoboErik */ 5143eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan private static int DAY_HEADER_HEIGHT = 45; 515f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan /** 516e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * The height of the day names/numbers for multi-day views 517e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik */ 518e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int MULTI_DAY_HEADER_HEIGHT = DAY_HEADER_HEIGHT; 519e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik /** 520e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * The height of the day names/numbers when viewing a single day 521e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik */ 522e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private static int ONE_DAY_HEADER_HEIGHT = DAY_HEADER_HEIGHT; 523e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik /** 524f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan * Max of all day events in a given day in this view. 525f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan */ 5262fda24534978f55711526dbde747aa50d68dec40RoboErik private int mMaxAlldayEvents; 5272fda24534978f55711526dbde747aa50d68dec40RoboErik /** 5282fda24534978f55711526dbde747aa50d68dec40RoboErik * A count of the number of allday events that were not drawn for each day 5292fda24534978f55711526dbde747aa50d68dec40RoboErik */ 5302fda24534978f55711526dbde747aa50d68dec40RoboErik private int[] mSkippedAlldayEvents; 5312fda24534978f55711526dbde747aa50d68dec40RoboErik /** 5322fda24534978f55711526dbde747aa50d68dec40RoboErik * The number of allDay events at which point we start hiding allDay events. 5332fda24534978f55711526dbde747aa50d68dec40RoboErik */ 5342fda24534978f55711526dbde747aa50d68dec40RoboErik private int mMaxUnexpandedAlldayEventCount = 4; 5352fda24534978f55711526dbde747aa50d68dec40RoboErik /** 5362fda24534978f55711526dbde747aa50d68dec40RoboErik * Whether or not to expand the allDay area to fill the screen 5372fda24534978f55711526dbde747aa50d68dec40RoboErik */ 5382fda24534978f55711526dbde747aa50d68dec40RoboErik private static boolean mShowAllAllDayEvents = false; 539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected int mNumDays = 7; 541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mNumHours = 10; 5423eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 5433eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan /** Width of the time line (list of hours) to the left. */ 544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mHoursWidth; 545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mDateStrWidth; 54646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** Top of the scrollable region i.e. below date labels and all day events */ 547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstCell; 54846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** First fully visibile hour */ 549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstHour = -1; 55046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** Distance between the mFirstCell and the top of first fully visible hour. */ 551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mFirstHourOffset; 552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mHourStrs; 553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mDayStrs; 554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String[] mDayStrs2Letter; 555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mIs24HourFormat; 556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 557056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final ArrayList<Event> mSelectedEvents = new ArrayList<Event>(); 558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mComputeSelectedEvents; 5598307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik private boolean mUpdateToast; 560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Event mSelectedEvent; 561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Event mPrevSelectedEvent; 562056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Rect mPrevBox = new Rect(); 563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected final Resources mResources; 5643eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan protected final Drawable mCurrentTimeLine; 5655b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik protected final Drawable mCurrentTimeAnimateLine; 5663eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan protected final Drawable mTodayHeaderDrawable; 5672fda24534978f55711526dbde747aa50d68dec40RoboErik protected final Drawable mExpandAlldayDrawable; 568cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik protected final Drawable mCollapseAlldayDrawable; 569f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan protected Drawable mAcceptedOrTentativeEventBoxDrawable; 570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String mAmString; 571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private String mPmString; 572056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final DeleteEventHelper mDeleteEventHelper; 5736d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private static int sCounter = 0; 574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 575056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final ContextMenuHandler mContextMenuHandler = new ContextMenuHandler(); 576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 577d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan ScaleGestureDetector mScaleGestureDetector; 578d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The initial state of the touch mode when we enter this view. 581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_INITIAL_STATE = 0; 583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates we just received the touch event and we are waiting to see if 586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * it is a tap or a scroll gesture. 587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_DOWN = 1; 589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates the touch gesture is a vertical scroll 592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_VSCROLL = 0x20; 594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 596146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Indicates the touch gesture is a horizontal scroll 597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int TOUCH_MODE_HSCROLL = 0x40; 599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mTouchMode = TOUCH_MODE_INITIAL_STATE; 601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The selection modes are HIDDEN, PRESSED, SELECTED, and LONGPRESS. 604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_HIDDEN = 0; 606ef2185bf0c7a80154a79788915db04d4f9e7ad4dMichael Chan private static final int SELECTION_PRESSED = 1; // D-pad down but not up yet 607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_SELECTED = 2; 608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private static final int SELECTION_LONGPRESS = 3; 609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int mSelectionMode = SELECTION_HIDDEN; 611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean mScrolling = false; 613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 6144f58287a1e02325337e39073a50bbb880094099fRoboErik private float mInitialScrollX; 6154f58287a1e02325337e39073a50bbb880094099fRoboErik private float mInitialScrollY; 6162fda24534978f55711526dbde747aa50d68dec40RoboErik 6175b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private boolean mAnimateToday = false; 6185b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private int mAnimateTodayAlpha = 0; 6195b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 6202fda24534978f55711526dbde747aa50d68dec40RoboErik // Animates the height of the allday region 6212fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator mAlldayAnimator; 6222fda24534978f55711526dbde747aa50d68dec40RoboErik // Animates the height of events in the allday region 6232fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator mAlldayEventAnimator; 6242fda24534978f55711526dbde747aa50d68dec40RoboErik // Animates the transparency of the more events text 6252fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator mMoreAlldayEventsAnimator; 6265b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik // Animates the current time marker when Today is pressed 6275b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik ObjectAnimator mTodayAnimator; 6282fda24534978f55711526dbde747aa50d68dec40RoboErik // whether or not an event is stopping because it was cancelled 6292fda24534978f55711526dbde747aa50d68dec40RoboErik private boolean mCancellingAnimations = false; 6302fda24534978f55711526dbde747aa50d68dec40RoboErik // tracks whether a touch originated in the allday area 6312fda24534978f55711526dbde747aa50d68dec40RoboErik private boolean mTouchStartedInAlldayArea = false; 6322fda24534978f55711526dbde747aa50d68dec40RoboErik 633056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final CalendarController mController; 634056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final ViewSwitcher mViewSwitcher; 635056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final GestureDetector mGestureDetector; 636056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final OverScroller mScroller; 637056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final EdgeEffect mEdgeEffectTop; 638056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final EdgeEffect mEdgeEffectBottom; 639433ba924de1ac26b923e2beb061812012749e4f3Michael Chan private boolean mCallEdgeEffectOnAbsorb; 640433ba924de1ac26b923e2beb061812012749e4f3Michael Chan private final int OVERFLING_DISTANCE; 641433ba924de1ac26b923e2beb061812012749e4f3Michael Chan private float mLastVelocity; 642433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 643056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final ScrollInterpolator mHScrollInterpolator; 644aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan private AccessibilityManager mAccessibilityMgr = null; 645aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan private boolean mIsAccessibilityEnabled = false; 6469ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan private boolean mTouchExplorationEnabled = false; 647056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final String mCreateNewEventString; 648056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final String mNewEventHintString; 649705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 650d190418220467c02327dd9b3ae1eae238889720bMichael Chan public DayView(Context context, CalendarController controller, 65175d9b567e1fd3b9c6945cd0afe28781f5a19c6c8Michael Chan ViewSwitcher viewSwitcher, EventLoader eventLoader, int numDays) { 652ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan super(context); 653aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mContext = context; 654aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan initAccessibilityVariables(); 655aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan 6562fda24534978f55711526dbde747aa50d68dec40RoboErik mResources = context.getResources(); 6579ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan mCreateNewEventString = mResources.getString(R.string.event_create); 658ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson mNewEventHintString = mResources.getString(R.string.day_view_new_event_hint); 65900671d5b9254772d223587b3b831d5816476f681Michael Chan mNumDays = numDays; 66009b1b2e1e7eb9bc291d4e70c993471d3c9ffa799Michael Chan 661e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik DATE_HEADER_FONT_SIZE = (int) mResources.getDimension(R.dimen.date_header_text_size); 662e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik DAY_HEADER_FONT_SIZE = (int) mResources.getDimension(R.dimen.day_label_text_size); 663e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik ONE_DAY_HEADER_HEIGHT = (int) mResources.getDimension(R.dimen.one_day_header_height); 664e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik DAY_HEADER_BOTTOM_MARGIN = (int) mResources.getDimension(R.dimen.day_header_bottom_margin); 665e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik EXPAND_ALL_DAY_BOTTOM_MARGIN = (int) mResources.getDimension(R.dimen.all_day_bottom_margin); 666e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik HOURS_TEXT_SIZE = (int) mResources.getDimension(R.dimen.hours_text_size); 667e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik AMPM_TEXT_SIZE = (int) mResources.getDimension(R.dimen.ampm_text_size); 668e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik MIN_HOURS_WIDTH = (int) mResources.getDimension(R.dimen.min_hours_width); 669e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik HOURS_LEFT_MARGIN = (int) mResources.getDimension(R.dimen.hours_left_margin); 670e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik HOURS_RIGHT_MARGIN = (int) mResources.getDimension(R.dimen.hours_right_margin); 671e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik MULTI_DAY_HEADER_HEIGHT = (int) mResources.getDimension(R.dimen.day_header_height); 67200671d5b9254772d223587b3b831d5816476f681Michael Chan int eventTextSizeId; 67300671d5b9254772d223587b3b831d5816476f681Michael Chan if (mNumDays == 1) { 67400671d5b9254772d223587b3b831d5816476f681Michael Chan eventTextSizeId = R.dimen.day_view_event_text_size; 67500671d5b9254772d223587b3b831d5816476f681Michael Chan } else { 67600671d5b9254772d223587b3b831d5816476f681Michael Chan eventTextSizeId = R.dimen.week_view_event_text_size; 67700671d5b9254772d223587b3b831d5816476f681Michael Chan } 67800671d5b9254772d223587b3b831d5816476f681Michael Chan EVENT_TEXT_FONT_SIZE = (int) mResources.getDimension(eventTextSizeId); 679ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson NEW_EVENT_HINT_FONT_SIZE = (int) mResources.getDimension(R.dimen.new_event_hint_text_size); 6805ca51369b44901fbab6da0ac67b3001c19f2ae29RoboErik MIN_EVENT_HEIGHT = mResources.getDimension(R.dimen.event_min_height); 681714c299ea5c05858e273d98efbacf20fedd328f1RoboErik MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT = MIN_EVENT_HEIGHT; 6825ca51369b44901fbab6da0ac67b3001c19f2ae29RoboErik EVENT_TEXT_TOP_MARGIN = (int) mResources.getDimension(R.dimen.event_text_vertical_margin); 6835ca51369b44901fbab6da0ac67b3001c19f2ae29RoboErik EVENT_TEXT_BOTTOM_MARGIN = EVENT_TEXT_TOP_MARGIN; 6845ca51369b44901fbab6da0ac67b3001c19f2ae29RoboErik EVENT_ALL_DAY_TEXT_TOP_MARGIN = EVENT_TEXT_TOP_MARGIN; 6855ca51369b44901fbab6da0ac67b3001c19f2ae29RoboErik EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN = EVENT_TEXT_TOP_MARGIN; 68609b1b2e1e7eb9bc291d4e70c993471d3c9ffa799Michael Chan 68795d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng EVENT_TEXT_LEFT_MARGIN = (int) mResources 68895d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng .getDimension(R.dimen.event_text_horizontal_margin); 68995d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng EVENT_TEXT_RIGHT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 69095d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng EVENT_ALL_DAY_TEXT_LEFT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 69195d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng EVENT_ALL_DAY_TEXT_RIGHT_MARGIN = EVENT_TEXT_LEFT_MARGIN; 69295d6fe0b672284a19699edc4727c366e3b0ccec7Peter Ng 693705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan if (mScale == 0) { 694e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 6952fda24534978f55711526dbde747aa50d68dec40RoboErik mScale = mResources.getDisplayMetrics().density; 696705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan if (mScale != 1) { 697705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan SINGLE_ALLDAY_HEIGHT *= mScale; 698705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan ALLDAY_TOP_MARGIN *= mScale; 699f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan MAX_HEIGHT_OF_ONE_ALLDAY_EVENT *= mScale; 700705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 701705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan NORMAL_FONT_SIZE *= mScale; 7028f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan GRID_LINE_LEFT_MARGIN *= mScale; 7038f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan HOURS_TOP_MARGIN *= mScale; 704705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan MIN_CELL_WIDTH_FOR_TEXT *= mScale; 7052fda24534978f55711526dbde747aa50d68dec40RoboErik MAX_UNEXPANDED_ALLDAY_HEIGHT *= mScale; 7062fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayEventHeight = (int) MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT; 707705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 708bd0e834aea317236d574f8738fe11a51fdc87968Erik CURRENT_TIME_LINE_HEIGHT *= mScale; 709bd0e834aea317236d574f8738fe11a51fdc87968Erik CURRENT_TIME_LINE_BORDER_WIDTH *= mScale; 710763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik CURRENT_TIME_LINE_SIDE_BUFFER *= mScale; 711763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik CURRENT_TIME_LINE_TOP_OFFSET *= mScale; 712bd0e834aea317236d574f8738fe11a51fdc87968Erik 713d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan MIN_Y_SPAN *= mScale; 714d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan MAX_CELL_HEIGHT *= mScale; 715697157470a6f0d8e7b806af9b4fb7fbe0bccae87Erik DEFAULT_CELL_HEIGHT *= mScale; 7163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_HEIGHT *= mScale; 7173eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_LEFT_MARGIN *= mScale; 7183eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_RIGHT_MARGIN *= mScale; 7193eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_LEFT_MARGIN *= mScale; 7203eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_RIGHT_MARGIN *= mScale; 7213eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan DAY_HEADER_ONE_DAY_BOTTOM_MARGIN *= mScale; 7223eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan CALENDAR_COLOR_SQUARE_SIZE *= mScale; 72311ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_TOP_MARGIN *= mScale; 72411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_BOTTOM_MARGIN *= mScale; 72525996100d6ea61888ebe54d7708a9a371bb12a55RoboErik ALL_DAY_EVENT_RECT_BOTTOM_MARGIN *= mScale; 72611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_LEFT_MARGIN *= mScale; 72711ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan EVENT_RECT_RIGHT_MARGIN *= mScale; 72825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik EVENT_RECT_STROKE_WIDTH *= mScale; 7292fda24534978f55711526dbde747aa50d68dec40RoboErik EVENT_SQUARE_WIDTH *= mScale; 7302fda24534978f55711526dbde747aa50d68dec40RoboErik EVENT_LINE_PADDING *= mScale; 73195f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan NEW_EVENT_MARGIN *= mScale; 73295f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan NEW_EVENT_WIDTH *= mScale; 73395f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan NEW_EVENT_MAX_LENGTH *= mScale; 734705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan } 735705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan } 736e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik HOURS_MARGIN = HOURS_LEFT_MARGIN + HOURS_RIGHT_MARGIN; 73700671d5b9254772d223587b3b831d5816476f681Michael Chan DAY_HEADER_HEIGHT = mNumDays == 1 ? ONE_DAY_HEADER_HEIGHT : MULTI_DAY_HEADER_HEIGHT; 738705043ffec0bcd8fd0348d4038ac34fd45b09818Michael Chan 7399175d29276c78a2a294ce2fce112432171ef7c7cRoboErik mCurrentTimeLine = mResources.getDrawable(R.drawable.timeline_indicator_holo_light); 7405b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mCurrentTimeAnimateLine = mResources 7415b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik .getDrawable(R.drawable.timeline_indicator_activated_holo_light); 7423eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mTodayHeaderDrawable = mResources.getDrawable(R.drawable.today_blue_week_holo_light); 74399704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan mExpandAlldayDrawable = mResources.getDrawable(R.drawable.ic_expand_holo_light); 74499704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan mCollapseAlldayDrawable = mResources.getDrawable(R.drawable.ic_collapse_holo_light); 745ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson mNewEventHintColor = mResources.getColor(R.color.new_event_hint_text_color); 746f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan mAcceptedOrTentativeEventBoxDrawable = mResources 747f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan .getDrawable(R.drawable.panel_month_event_holo_light); 74825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik 749ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mEventLoader = eventLoader; 750146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry = new EventGeometry(); 751146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setMinEventHeight(MIN_EVENT_HEIGHT); 752146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setHourGap(HOUR_GAP); 753e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mEventGeometry.setCellMargin(DAY_GAP); 75420b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik mLongPressItems = new CharSequence[] { 75520b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik mResources.getString(R.string.new_event_dialog_option) 75620b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik }; 75720b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik mLongPressTitle = mResources.getString(R.string.new_event_dialog_label); 758ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mDeleteEventHelper = new DeleteEventHelper(context, null, false /* don't exit when done */); 759666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 760ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mController = controller; 761ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher = viewSwitcher; 762ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mGestureDetector = new GestureDetector(context, new CalendarGestureListener()); 763d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mScaleGestureDetector = new ScaleGestureDetector(getContext(), this); 764d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight == 0) { 765d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = Utils.getSharedPreference(mContext, 766d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan GeneralPreferences.KEY_DEFAULT_CELL_HEIGHT, DEFAULT_CELL_HEIGHT); 767d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 7683f6328f579b05c02606572c777541b97aa04f9f3Michael Chan mScroller = new OverScroller(context); 7692c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan mHScrollInterpolator = new ScrollInterpolator(); 770433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop = new EdgeEffect(context); 771433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom = new EdgeEffect(context); 772ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson ViewConfiguration vc = ViewConfiguration.get(context); 7739e196e46b238e6bca1ef86c7d673807b78ab7016Michael Chan mOnDownDelay = ViewConfiguration.getTapTimeout(); 774ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson OVERFLING_DISTANCE = vc.getScaledOverflingDistance(); 775433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 776ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan init(context); 777146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 778146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 779ea3f117db073ae796453479d00e9c7664d4471c5RoboErik @Override 780ea3f117db073ae796453479d00e9c7664d4471c5RoboErik protected void onAttachedToWindow() { 781ea3f117db073ae796453479d00e9c7664d4471c5RoboErik if (mHandler == null) { 782ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler = getHandler(); 783ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.post(mUpdateCurrentTime); 784ea3f117db073ae796453479d00e9c7664d4471c5RoboErik } 785ea3f117db073ae796453479d00e9c7664d4471c5RoboErik } 786ea3f117db073ae796453479d00e9c7664d4471c5RoboErik 787146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void init(Context context) { 788146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setFocusable(true); 789146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 790146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allow focus in touch mode so that we can do keyboard shortcuts 791146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // even after we've entered touch mode. 792146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setFocusableInTouchMode(true); 793146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setClickable(true); 794146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project setOnCreateContextMenuListener(this); 795146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 796487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstDayOfWeek = Utils.getFirstDayOfWeek(context); 797146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 798731f1cb808b7586b93615b408ab2636081fab0dcErik mCurrentTime = new Time(Utils.getTimeZone(context, mTZUpdater)); 799bd0e834aea317236d574f8738fe11a51fdc87968Erik long currentTime = System.currentTimeMillis(); 800bd0e834aea317236d574f8738fe11a51fdc87968Erik mCurrentTime.set(currentTime); 801bd0e834aea317236d574f8738fe11a51fdc87968Erik mTodayJulianDay = Time.getJulianDay(currentTime, mCurrentTime.gmtoff); 802bd0e834aea317236d574f8738fe11a51fdc87968Erik 80364b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok mWeek_saturdayColor = mResources.getColor(R.color.week_saturday); 80464b3e63d59967eeb11e1d8328c74ee335abc0ffbsatok mWeek_sundayColor = mResources.getColor(R.color.week_sunday); 805d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarDateBannerTextColor = mResources.getColor(R.color.calendar_date_banner_text_color); 806cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan mFutureBgColorRes = mResources.getColor(R.color.calendar_future_bg_color); 807e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mBgColor = mResources.getColor(R.color.calendar_hour_background); 808d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan mCalendarAmPmLabel = mResources.getColor(R.color.calendar_ampm_label); 809ba902466b19b11d587468e354edc58e542707747Michael Chan mCalendarGridAreaSelected = mResources.getColor(R.color.calendar_grid_area_selected); 810e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mCalendarGridLineInnerHorizontalColor = mResources 811e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik .getColor(R.color.calendar_grid_line_inner_horizontal_color); 812e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mCalendarGridLineInnerVerticalColor = mResources 813e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik .getColor(R.color.calendar_grid_line_inner_vertical_color); 8148f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mCalendarHourLabelColor = mResources.getColor(R.color.calendar_hour_label); 815146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPressedColor = mResources.getColor(R.color.pressed); 816056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson mClickedColor = mResources.getColor(R.color.day_event_clicked_background_color); 817146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextColor = mResources.getColor(R.color.calendar_event_text_color); 818e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mMoreEventsTextColor = mResources.getColor(R.color.month_event_other_color); 81911638ad4fb56b978770aebe75deac7a0e6ac60d2Erik 820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setTextSize(EVENT_TEXT_FONT_SIZE); 821146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setTextAlign(Paint.Align.LEFT); 822146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventTextPaint.setAntiAlias(true); 823146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 824146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int gridLineColor = mResources.getColor(R.color.calendar_grid_line_highlight_color); 825146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mSelectionPaint; 826146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setColor(gridLineColor); 8273937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setStyle(Style.FILL); 828146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(false); 829146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 830146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p = mPaint; 831146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 832146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 833146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allocate space for 2 weeks worth of weekday names so that we can 834146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // easily start the week display at any week day. 835146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs = new String[14]; 836146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 837146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also create an array of 2-letter abbreviations. 838146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter = new String[14]; 839146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 840146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) { 841146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int index = i - Calendar.SUNDAY; 842146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // e.g. Tue for Tuesday 843e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mDayStrs[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_MEDIUM) 844e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik .toUpperCase(); 845146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs[index + 7] = mDayStrs[index]; 846146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // e.g. Tu for Tuesday 847e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mDayStrs2Letter[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_SHORT) 848e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik .toUpperCase(); 84952b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer 85052b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer // If we don't have 2-letter day strings, fall back to 1-letter. 85152b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer if (mDayStrs2Letter[index].equals(mDayStrs[index])) { 85252b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer mDayStrs2Letter[index] = DateUtils.getDayOfWeekString(i, DateUtils.LENGTH_SHORTEST); 85352b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer } 85452b2d70115e88b408c994db0d2b1889c9fb48527Eric Fischer 855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDayStrs2Letter[index + 7] = mDayStrs2Letter[index]; 856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 857146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out how much space we need for the 3-letter abbrev names 859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // in the worst case. 8603eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 861146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 862146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] dateStrs = {" 28", " 30"}; 863146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDateStrWidth = computeMaxStringWidth(0, dateStrs, p); 8643eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 865146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mDateStrWidth += computeMaxStringWidth(0, mDayStrs, p); 866146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 867e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextSize(HOURS_TEXT_SIZE); 868146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(null); 86961a2e87e7412281d17e86ccff4352cbf32fe77e7Michael Chan handleOnResume(); 870146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 871e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mAmString = DateUtils.getAMPMString(Calendar.AM).toUpperCase(); 872e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mPmString = DateUtils.getAMPMString(Calendar.PM).toUpperCase(); 873146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] ampm = {mAmString, mPmString}; 874e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextSize(AMPM_TEXT_SIZE); 875e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mHoursWidth = Math.max(HOURS_MARGIN, computeMaxStringWidth(mHoursWidth, ampm, p) 876e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik + HOURS_RIGHT_MARGIN); 8778f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mHoursWidth = Math.max(MIN_HOURS_WIDTH, mHoursWidth); 878146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 879146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project LayoutInflater inflater; 880146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 881146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView = inflater.inflate(R.layout.bubble_event, null); 882146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView.setLayoutParams(new ViewGroup.LayoutParams( 883df279e3f9d5b0f189f812c52aca78d18178e4445Romain Guy ViewGroup.LayoutParams.MATCH_PARENT, 884146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ViewGroup.LayoutParams.WRAP_CONTENT)); 885146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup = new PopupWindow(context); 886146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setContentView(mPopupView); 887146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Resources.Theme dialogTheme = getResources().newTheme(); 888146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dialogTheme.applyStyle(android.R.style.Theme_Dialog, true); 889146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TypedArray ta = dialogTheme.obtainStyledAttributes(new int[] { 890146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project android.R.attr.windowBackground }); 891146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setBackgroundDrawable(ta.getDrawable(0)); 892146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ta.recycle(); 893146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 894146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Enable touching the popup window 895146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopupView.setOnClickListener(this); 896cd405a28e6821b116dcf3c531805d0c90b6cc08cErik // Catch long clicks for creating a new event 897cd405a28e6821b116dcf3c531805d0c90b6cc08cErik setOnLongClickListener(this); 898146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 899731f1cb808b7586b93615b408ab2636081fab0dcErik mBaseDate = new Time(Utils.getTimeZone(context, mTZUpdater)); 900146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = System.currentTimeMillis(); 901146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.set(millis); 902146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 903146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour = new int[mNumDays]; 904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent = new boolean[mNumDays]; 90502041687c35441e8a21cb763f1fc3a26525292efDavid Brown 90602041687c35441e8a21cb763f1fc3a26525292efDavid Brown // mLines is the array of points used with Canvas.drawLines() in 90702041687c35441e8a21cb763f1fc3a26525292efDavid Brown // drawGridBackground() and drawAllDayEvents(). Its size depends 90802041687c35441e8a21cb763f1fc3a26525292efDavid Brown // on the max number of lines that can ever be drawn by any single 90902041687c35441e8a21cb763f1fc3a26525292efDavid Brown // drawLines() call in either of those methods. 91002041687c35441e8a21cb763f1fc3a26525292efDavid Brown final int maxGridLines = (24 + 1) // max horizontal lines we might draw 911e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik + (mNumDays + 1); // max vertical lines we might draw 91202041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines = new float[maxGridLines * 4]; 913146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 914146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 915146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 916146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * This is called when the popup window is pressed. 917146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 918146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void onClick(View v) { 919146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (v == mPopupView) { 920146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pretend it was a trackball click because that will always 921146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // jump to the "View event" screen. 922146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball */); 923146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 924146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 925146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 92661a2e87e7412281d17e86ccff4352cbf32fe77e7Michael Chan public void handleOnResume() { 927aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan initAccessibilityVariables(); 928cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan if(Utils.getSharedPreference(mContext, OtherPreferences.KEY_OTHER_1, false)) { 929cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan mFutureBgColor = 0; 930cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } else { 931cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan mFutureBgColor = mFutureBgColorRes; 932cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } 933ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mIs24HourFormat = DateFormat.is24HourFormat(mContext); 93469ab334d6988eda70ba53618506d23ebf7d7b405Erik mHourStrs = mIs24HourFormat ? CalendarData.s24Hours : CalendarData.s12HoursNoAmPm; 93561a2e87e7412281d17e86ccff4352cbf32fe77e7Michael Chan mFirstDayOfWeek = Utils.getFirstDayOfWeek(mContext); 936989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mLastSelectionDayForAccessibility = 0; 937989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mLastSelectionHourForAccessibility = 0; 938989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mLastSelectedEventForAccessibility = null; 939f7cf45455ce8cc5588479dcbb5d876f7638f79dcRoboErik mSelectionMode = SELECTION_HIDDEN; 94069ab334d6988eda70ba53618506d23ebf7d7b405Erik } 94169ab334d6988eda70ba53618506d23ebf7d7b405Erik 942aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan private void initAccessibilityVariables() { 943aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mAccessibilityMgr = (AccessibilityManager) mContext 944aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan .getSystemService(Service.ACCESSIBILITY_SERVICE); 945aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mIsAccessibilityEnabled = mAccessibilityMgr != null && mAccessibilityMgr.isEnabled(); 946aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mTouchExplorationEnabled = isTouchExplorationEnabled(); 947aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 948aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan 949146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Returns the start of the selected time in milliseconds since the epoch. 951146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 952146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return selected time in UTC milliseconds since the epoch. 953146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 954146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long getSelectedTimeInMillis() { 955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 956146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 957146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 959146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 960146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time.normalize(true /* ignore isDst */); 963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 964146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time getSelectedTime() { 966146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 968146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 969146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 970146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 971146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 972146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 973146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.normalize(true /* ignore isDst */); 974146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time; 975146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 976146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 977989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson Time getSelectedTimeForAccessibility() { 978989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson Time time = new Time(mBaseDate); 979989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson time.setJulianDay(mSelectionDayForAccessibility); 980989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson time.hour = mSelectionHourForAccessibility; 981989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson 982989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson // We ignore the "isDst" field because we want normalize() to figure 983989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson // out the correct DST value and not adjust the selected time based 984989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson // on the current setting of DST. 985989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson time.normalize(true /* ignore isDst */); 986989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson return time; 987989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson } 988989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson 989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 990146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Returns the start of the selected time in minutes since midnight, 991146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * local time. The derived class must ensure that this is consistent 992146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * with the return value from getSelectedTimeInMillis(). 993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int getSelectedMinutesSinceMidnight() { 995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return mSelectionHour * MINUTES_PER_HOUR; 996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 99846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int getFirstVisibleHour() { 99946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return mFirstHour; 100046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 100146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 100246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan void setFirstVisibleHour(int firstHour) { 100346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mFirstHour = firstHour; 100446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mFirstHourOffset = 0; 100546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 100646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 10075b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void setSelected(Time time, boolean ignoreTime, boolean animateToday) { 1008146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mBaseDate.set(time); 1009989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(mBaseDate.hour); 1010989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(null); 1011146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 1012146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = mBaseDate.toMillis(false /* use isDst */); 1013989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedDay(Time.getJulianDay(millis, mBaseDate.gmtoff)); 1014146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1015146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1016146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 101746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int gotoY = Integer.MIN_VALUE; 101846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 101946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (!ignoreTime && mGridAreaHeight != -1) { 102046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int lastHour = 0; 102146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 102246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mBaseDate.hour < mFirstHour) { 102346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Above visible region 102446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan gotoY = mBaseDate.hour * (mCellHeight + HOUR_GAP); 102546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 102646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan lastHour = (mGridAreaHeight - mFirstHourOffset) / (mCellHeight + HOUR_GAP) 102746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan + mFirstHour; 102846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 102946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mBaseDate.hour >= lastHour) { 103046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Below visible region 103146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 103246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // target hour + 1 (to give it room to see the event) - 103346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // grid height (to get the y of the top of the visible 103446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // region) 103555a26d7062d5aa1a1b001b7271bb137276ab807eErik gotoY = (int) ((mBaseDate.hour + 1 + mBaseDate.minute / 60.0f) 103646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * (mCellHeight + HOUR_GAP) - mGridAreaHeight); 103746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 103846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 103946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 104046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) { 104146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan Log.e(TAG, "Go " + gotoY + " 1st " + mFirstHour + ":" + mFirstHourOffset + "CH " 104246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan + (mCellHeight + HOUR_GAP) + " lh " + lastHour + " gh " + mGridAreaHeight 104346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan + " ymax " + mMaxViewStartY); 104446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 104546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 104646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (gotoY > mMaxViewStartY) { 104746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan gotoY = mMaxViewStartY; 104846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else if (gotoY < 0 && gotoY != Integer.MIN_VALUE) { 104946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan gotoY = 0; 105046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 105146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 105246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 1053146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 1054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1055146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = true; 1056146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 105746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 10585b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik boolean delayAnimateToday = false; 105946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (gotoY != Integer.MIN_VALUE) { 10605b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik ValueAnimator scrollAnim = ObjectAnimator.ofInt(this, "viewStartY", mViewStartY, gotoY); 10615b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik scrollAnim.setDuration(GOTO_SCROLL_DURATION); 106246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan scrollAnim.setInterpolator(new AccelerateDecelerateInterpolator()); 106346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan scrollAnim.addListener(mAnimatorListener); 106446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan scrollAnim.start(); 10655b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik delayAnimateToday = true; 10665b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 10675b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (animateToday) { 10685b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik synchronized (mTodayAnimatorListener) { 10695b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mTodayAnimator != null) { 10705b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.removeAllListeners(); 10715b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.cancel(); 10725b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 10735b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator = ObjectAnimator.ofInt(this, "animateTodayAlpha", 10745b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateTodayAlpha, 255); 10755b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateToday = true; 10765b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimatorListener.setFadingIn(true); 10775b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimatorListener.setAnimator(mTodayAnimator); 10785b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.addListener(mTodayAnimatorListener); 10795b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.setDuration(150); 10805b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (delayAnimateToday) { 10815b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.setStartDelay(GOTO_SCROLL_DURATION); 10825b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 10835b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mTodayAnimator.start(); 10845b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 108546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 1086aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan sendAccessibilityEventAsNeeded(false); 108746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 108846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 108946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public void setViewStartY(int viewStartY) { 109046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (viewStartY > mMaxViewStartY) { 109146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan viewStartY = mMaxViewStartY; 109246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 109346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 109446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mViewStartY = viewStartY; 109546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 109646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan computeFirstHour(); 109746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan invalidate(); 1098146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 11005b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void setAnimateTodayAlpha(int todayAlpha) { 11015b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateTodayAlpha = todayAlpha; 11025b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik invalidate(); 11035b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 11045b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 1105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public Time getSelectedDay() { 1106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time time = new Time(mBaseDate); 1107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.setJulianDay(mSelectionDay); 1108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.hour = mSelectionHour; 1109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We ignore the "isDst" field because we want normalize() to figure 1111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // out the correct DST value and not adjust the selected time based 1112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on the current setting of DST. 1113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project time.normalize(true /* ignore isDst */); 1114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return time; 1115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1117eaafa2b48be7194a61754604ae37b3d62e9118d8Erik public void updateTitle() { 1118eaafa2b48be7194a61754604ae37b3d62e9118d8Erik Time start = new Time(mBaseDate); 1119eaafa2b48be7194a61754604ae37b3d62e9118d8Erik start.normalize(true); 1120eaafa2b48be7194a61754604ae37b3d62e9118d8Erik Time end = new Time(start); 1121eaafa2b48be7194a61754604ae37b3d62e9118d8Erik end.monthDay += mNumDays - 1; 1122eaafa2b48be7194a61754604ae37b3d62e9118d8Erik // Move it forward one minute so the formatter doesn't lose a day 1123eaafa2b48be7194a61754604ae37b3d62e9118d8Erik end.minute += 1; 1124eaafa2b48be7194a61754604ae37b3d62e9118d8Erik end.normalize(true); 1125eaafa2b48be7194a61754604ae37b3d62e9118d8Erik 11269e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan long formatFlags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR; 11279e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan if (mNumDays != 1) { 11289e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan // Don't show day of the month if for multi-day view 11299e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan formatFlags |= DateUtils.FORMAT_NO_MONTH_DAY; 11309e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan 11319e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan // Abbreviate the month if showing multiple months 11329e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan if (start.month != end.month) { 11339e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan formatFlags |= DateUtils.FORMAT_ABBREV_MONTH; 11349e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan } 11359e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan } 11369e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan 1137f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mController.sendEvent(this, EventType.UPDATE_TITLE, start, end, null, -1, ViewType.CURRENT, 11389e9e0678fe1969659dede3909c2cab6d2c3e5c8bMichael Chan formatFlags, null, null); 1139eaafa2b48be7194a61754604ae37b3d62e9118d8Erik } 1140eaafa2b48be7194a61754604ae37b3d62e9118d8Erik 114183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan /** 1142487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * return a negative number if "time" is comes before the visible time 1143487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * range, a positive number if "time" is after the visible time range, and 0 1144487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan * if it is in the visible time range. 114583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan */ 1146487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan public int compareToVisibleTimeRange(Time time) { 1147487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 1148487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedHour = mBaseDate.hour; 1149487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedMinute = mBaseDate.minute; 1150487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int savedSec = mBaseDate.second; 1151487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 1152487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.hour = 0; 1153487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.minute = 0; 1154487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.second = 0; 1155487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 1156030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) { 1157030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown Log.d(TAG, "Begin " + mBaseDate.toString()); 1158030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown Log.d(TAG, "Diff " + time.toString()); 1159030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown } 1160487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 116183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan // Compare beginning of range 116283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan int diff = Time.compare(time, mBaseDate); 1163487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (diff > 0) { 1164487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // Compare end of range 1165487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.monthDay += mNumDays; 1166487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.normalize(true); 1167487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = Time.compare(time, mBaseDate); 1168487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 1169030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "End " + mBaseDate.toString()); 1170487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 1171487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.monthDay -= mNumDays; 1172487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.normalize(true); 1173487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan if (diff < 0) { 1174487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // in visible time 1175487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = 0; 1176487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } else if (diff == 0) { 1177487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan // Midnight of following day 1178487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan diff = 1; 1179487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 118083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 118183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 1182030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown if (DEBUG) Log.d(TAG, "Diff: " + diff); 118383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 1184487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.hour = savedHour; 1185487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.minute = savedMinute; 1186487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mBaseDate.second = savedSec; 1187487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan return diff; 118883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 118983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 1190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void recalc() { 1191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Set the base date to the beginning of the week if we are displaying 1192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // 7 days at a time. 1193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 7) { 11946d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan adjustToBeginningOfWeek(mBaseDate); 1195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final long start = mBaseDate.toMillis(false /* use isDst */); 1198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstJulianDay = Time.getJulianDay(start, mBaseDate.gmtoff); 1199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastJulianDay = mFirstJulianDay + mNumDays - 1; 1200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mMonthLength = mBaseDate.getActualMaximum(Time.MONTH_DAY); 1202487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstVisibleDate = mBaseDate.monthDay; 1203487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mFirstVisibleDayOfWeek = mBaseDate.weekDay; 1204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 12066d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private void adjustToBeginningOfWeek(Time time) { 12076d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan int dayOfWeek = time.weekDay; 12086d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan int diff = dayOfWeek - mFirstDayOfWeek; 12096d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (diff != 0) { 12106d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (diff < 0) { 12116d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan diff += 7; 12126d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 12136d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan time.monthDay -= diff; 12146d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan time.normalize(true /* ignore isDst */); 12156d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 12166d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 12176d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 1218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected void onSizeChanged(int width, int height, int oldw, int oldh) { 1220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewWidth = width; 1221146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewHeight = height; 1222433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop.setSize(mViewWidth, mViewHeight); 1223433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom.setSize(mViewWidth, mViewHeight); 1224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int gridAreaWidth = width - mHoursWidth; 1225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mCellWidth = (gridAreaWidth - (mNumDays * DAY_GAP)) / mNumDays; 1226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1227d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan // This would be about 1 day worth in a 7 day view 1228d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan mHorizontalSnapBackThreshold = width / 7; 1229d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan 1230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = new Paint(); 1231e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextSize(HOURS_TEXT_SIZE); 1232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHoursTextHeight = (int) Math.abs(p.ascent()); 1233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project remeasure(width, height); 1234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 123646b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa /** 123746b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa * Measures the space needed for various parts of the view after 123846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa * loading new events. This can change if there are all-day events. 123946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa */ 1240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void remeasure(int width, int height) { 12412fda24534978f55711526dbde747aa50d68dec40RoboErik // Shrink to fit available space but make sure we can display at least two events 12422fda24534978f55711526dbde747aa50d68dec40RoboErik MAX_UNEXPANDED_ALLDAY_HEIGHT = (int) (MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT * 4); 12432fda24534978f55711526dbde747aa50d68dec40RoboErik MAX_UNEXPANDED_ALLDAY_HEIGHT = Math.min(MAX_UNEXPANDED_ALLDAY_HEIGHT, height / 6); 12442fda24534978f55711526dbde747aa50d68dec40RoboErik MAX_UNEXPANDED_ALLDAY_HEIGHT = Math.max(MAX_UNEXPANDED_ALLDAY_HEIGHT, 12452fda24534978f55711526dbde747aa50d68dec40RoboErik (int) MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT * 2); 12462fda24534978f55711526dbde747aa50d68dec40RoboErik mMaxUnexpandedAlldayEventCount = 12472fda24534978f55711526dbde747aa50d68dec40RoboErik (int) (MAX_UNEXPANDED_ALLDAY_HEIGHT / MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT); 1248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear the array of earliest start times, and the array 1250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // indicating presence of an all-day event. 1251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++) { 1252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEarliestStartHour[day] = 25; // some big number 1253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mHasAllDayEvent[day] = false; 1254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 12562fda24534978f55711526dbde747aa50d68dec40RoboErik int maxAllDayEvents = mMaxAlldayEvents; 1257c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa 12582fda24534978f55711526dbde747aa50d68dec40RoboErik // The min is where 24 hours cover the entire visible area 12597939fa59d64c1e6ac95f352e24d761dbacf67547RoboErik mMinCellHeight = Math.max((height - DAY_HEADER_HEIGHT) / 24, (int) MIN_EVENT_HEIGHT); 12602fda24534978f55711526dbde747aa50d68dec40RoboErik if (mCellHeight < mMinCellHeight) { 12612fda24534978f55711526dbde747aa50d68dec40RoboErik mCellHeight = mMinCellHeight; 1262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 12649c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan // Calculate mAllDayHeight 12653eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mFirstCell = DAY_HEADER_HEIGHT; 1266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int allDayHeight = 0; 1267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxAllDayEvents > 0) { 12682fda24534978f55711526dbde747aa50d68dec40RoboErik int maxAllAllDayHeight = height - DAY_HEADER_HEIGHT - MIN_HOURS_HEIGHT; 1269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is at most one all-day event per day, then use less 1270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // space (but more than the space for a single event). 1271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxAllDayEvents == 1) { 1272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project allDayHeight = SINGLE_ALLDAY_HEIGHT; 12732fda24534978f55711526dbde747aa50d68dec40RoboErik } else if (maxAllDayEvents <= mMaxUnexpandedAlldayEventCount){ 1274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Allow the all-day area to grow in height depending on the 1275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // number of all-day events we need to show, up to a limit. 1276f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan allDayHeight = maxAllDayEvents * MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 12772fda24534978f55711526dbde747aa50d68dec40RoboErik if (allDayHeight > MAX_UNEXPANDED_ALLDAY_HEIGHT) { 12782fda24534978f55711526dbde747aa50d68dec40RoboErik allDayHeight = MAX_UNEXPANDED_ALLDAY_HEIGHT; 12792fda24534978f55711526dbde747aa50d68dec40RoboErik } 12802fda24534978f55711526dbde747aa50d68dec40RoboErik } else { 12812fda24534978f55711526dbde747aa50d68dec40RoboErik // if we have more than the magic number, check if we're animating 12822fda24534978f55711526dbde747aa50d68dec40RoboErik // and if not adjust the sizes appropriately 12832fda24534978f55711526dbde747aa50d68dec40RoboErik if (mAnimateDayHeight != 0) { 12842fda24534978f55711526dbde747aa50d68dec40RoboErik // Don't shrink the space past the final allDay space. The animation 12852fda24534978f55711526dbde747aa50d68dec40RoboErik // continues to hide the last event so the more events text can 12862fda24534978f55711526dbde747aa50d68dec40RoboErik // fade in. 12872fda24534978f55711526dbde747aa50d68dec40RoboErik allDayHeight = Math.max(mAnimateDayHeight, MAX_UNEXPANDED_ALLDAY_HEIGHT); 12882fda24534978f55711526dbde747aa50d68dec40RoboErik } else { 12892fda24534978f55711526dbde747aa50d68dec40RoboErik // Try to fit all the events in 12902fda24534978f55711526dbde747aa50d68dec40RoboErik allDayHeight = (int) (maxAllDayEvents * MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT); 12912fda24534978f55711526dbde747aa50d68dec40RoboErik // But clip the area depending on which mode we're in 12922fda24534978f55711526dbde747aa50d68dec40RoboErik if (!mShowAllAllDayEvents && allDayHeight > MAX_UNEXPANDED_ALLDAY_HEIGHT) { 1293e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik allDayHeight = (int) (mMaxUnexpandedAlldayEventCount * 1294e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT); 12952fda24534978f55711526dbde747aa50d68dec40RoboErik } else if (allDayHeight > maxAllAllDayHeight) { 12962fda24534978f55711526dbde747aa50d68dec40RoboErik allDayHeight = maxAllAllDayHeight; 12972fda24534978f55711526dbde747aa50d68dec40RoboErik } 1298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 13003eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mFirstCell = DAY_HEADER_HEIGHT + allDayHeight + ALLDAY_TOP_MARGIN; 1301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 13022fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = false; 1303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 13042fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayHeight = allDayHeight; 1305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mGridAreaHeight = height - mFirstCell; 1307d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 13082fda24534978f55711526dbde747aa50d68dec40RoboErik // Set up the expand icon position 1309e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int allDayIconWidth = mExpandAlldayDrawable.getIntrinsicWidth(); 1310e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mExpandAllDayRect.left = Math.max((mHoursWidth - allDayIconWidth) / 2, 1311e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik EVENT_ALL_DAY_TEXT_LEFT_MARGIN); 1312e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mExpandAllDayRect.right = Math.min(mExpandAllDayRect.left + allDayIconWidth, mHoursWidth 1313e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik - EVENT_ALL_DAY_TEXT_RIGHT_MARGIN); 1314cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mExpandAllDayRect.bottom = mFirstCell - EXPAND_ALL_DAY_BOTTOM_MARGIN; 1315e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mExpandAllDayRect.top = mExpandAllDayRect.bottom 1316e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik - mExpandAlldayDrawable.getIntrinsicHeight(); 1317e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 131846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mNumHours = mGridAreaHeight / (mCellHeight + HOUR_GAP); 1319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEventGeometry.setHourHeight(mCellHeight); 1320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 132127d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa final long minimumDurationMillis = (long) 132227d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa (MIN_EVENT_HEIGHT * DateUtils.MINUTE_IN_MILLIS / (mCellHeight / 60.0f)); 13232fda24534978f55711526dbde747aa50d68dec40RoboErik Event.computePositions(mEvents, minimumDurationMillis); 132446b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa 1325c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Compute the top of our reachable view 1326c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mMaxViewStartY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP) - mGridAreaHeight; 1327d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (DEBUG) { 1328d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.e(TAG, "mViewStartY: " + mViewStartY); 1329d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Log.e(TAG, "mMaxViewStartY: " + mMaxViewStartY); 1330d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 1331d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mViewStartY > mMaxViewStartY) { 1332d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = mMaxViewStartY; 1333d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan computeFirstHour(); 1334d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 1335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour == -1) { 1337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initFirstHour(); 1338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = 0; 1339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // When we change the base date, the number of all-day events may 1342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // change and that changes the cell height. When we switch dates, 1343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // we use the mFirstHourOffset from the previous view, but that may 1344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // be too large for the new view if the cell height is smaller. 1345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHourOffset >= mCellHeight + HOUR_GAP) { 1346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = mCellHeight + HOUR_GAP - 1; 1347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mFirstHour * (mCellHeight + HOUR_GAP) - mFirstHourOffset; 1349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 135046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa final int eventAreaWidth = mNumDays * (mCellWidth + DAY_GAP); 1351666fc5e8ddbac15c951aad738bd818ee307eae42Erik //When we get new events we don't want to dismiss the popup unless the event changes 1352666fc5e8ddbac15c951aad738bd818ee307eae42Erik if (mSelectedEvent != null && mLastPopupEventID != mSelectedEvent.id) { 1353666fc5e8ddbac15c951aad738bd818ee307eae42Erik mPopup.dismiss(); 1354666fc5e8ddbac15c951aad738bd818ee307eae42Erik } 1355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setWidth(eventAreaWidth - 20); 1356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); 1357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Initialize the state for another view. The given view is one that has 1361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * its own bitmap and will use an animation to replace the current view. 1362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The current view and new view are either both Week views or both Day 1363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * views. They differ in their base date. 1364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 1365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param view the view to initialize. 1366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1367d190418220467c02327dd9b3ae1eae238889720bMichael Chan private void initView(DayView view) { 1368989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson view.setSelectedHour(mSelectionHour); 1369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mSelectedEvents.clear(); 1370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mComputeSelectedEvents = true; 1371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mFirstHour = mFirstHour; 1372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mFirstHourOffset = mFirstHourOffset; 1373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.remeasure(getWidth(), getHeight()); 13742fda24534978f55711526dbde747aa50d68dec40RoboErik view.initAllDayHeights(); 1375e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 1376989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson view.setSelectedEvent(null); 1377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.mPrevSelectedEvent = null; 1378487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan view.mFirstDayOfWeek = mFirstDayOfWeek; 1379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (view.mEvents.size() > 0) { 13802fda24534978f55711526dbde747aa50d68dec40RoboErik view.mSelectionAllday = mSelectionAllday; 1381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 13822fda24534978f55711526dbde747aa50d68dec40RoboErik view.mSelectionAllday = false; 1383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Redraw the screen so that the selection box will be redrawn. We may 1386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // have scrolled to a different part of the day in some other view 1387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // so the selection box in this view may no longer be visible. 1388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.recalc(); 1389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Switch to another view based on what was selected (an event or a free 1393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * slot) and how it was selected (by touch or by trackball). 1394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 1395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param trackBallSelection true if the selection was made using the 1396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * trackball. 1397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void switchViews(boolean trackBallSelection) { 1399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 1400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 1402666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 1403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays > 1) { 1404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the Week view. 1405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // With touch, we always switch to Day/Agenda View 1406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // With track ball, if we selected a free slot, then create an event. 1407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected a specific event, switch to EventInfo view. 1408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (trackBallSelection) { 1409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 1410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EditEvent view 1411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 1412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 1413edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan long extraLong = 0; 1414edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan if (mSelectionAllday) { 1415edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan extraLong = CalendarController.EXTRA_CREATE_ALL_DAY; 1416edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan } 1417edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan mController.sendEventRelatedEventWithExtra(this, EventType.CREATE_EVENT, -1, 1418edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan startMillis, endMillis, -1, -1, extraLong, -1); 1419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1420aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (mIsAccessibilityEnabled) { 1421aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mAccessibilityMgr.interrupt(); 1422aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 1423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EventInfo view 14249e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 142587f993ff96172f508d3f241f8a425f953c7eb739RoboErik selectedEvent.startMillis, selectedEvent.endMillis, 0, 0, 142687f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis()); 1427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This was a touch selection. If the touch selected a single 1430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // unambiguous event, then view that event. Otherwise go to 1431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Day/Agenda view. 1432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvents.size() == 1) { 1433aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (mIsAccessibilityEnabled) { 1434aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mAccessibilityMgr.interrupt(); 1435aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 14369e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 143787f993ff96172f508d3f241f8a425f953c7eb739RoboErik selectedEvent.startMillis, selectedEvent.endMillis, 0, 0, 143887f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis()); 1439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is the Day view. 1443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected a free slot, then create an event. 1444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we selected an event, then go to the EventInfo view. 1445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectedEvent == null) { 1446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Switch to the EditEvent view 1447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 1448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 1449edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan long extraLong = 0; 1450edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan if (mSelectionAllday) { 1451edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan extraLong = CalendarController.EXTRA_CREATE_ALL_DAY; 1452edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan } 1453edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan mController.sendEventRelatedEventWithExtra(this, EventType.CREATE_EVENT, -1, 1454edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan startMillis, endMillis, -1, -1, extraLong, -1); 1455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1456aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (mIsAccessibilityEnabled) { 1457aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mAccessibilityMgr.interrupt(); 1458aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 14599e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT, selectedEvent.id, 146087f993ff96172f508d3f241f8a425f953c7eb739RoboErik selectedEvent.startMillis, selectedEvent.endMillis, 0, 0, 146187f993ff96172f508d3f241f8a425f953c7eb739RoboErik getSelectedTimeInMillis()); 1462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 1468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 1469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long duration = event.getEventTime() - event.getDownTime(); 1470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (keyCode) { 1472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 1473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_HIDDEN) { 1474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Don't do anything unless the selection is visible. 1475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_PRESSED) { 1479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This was the first press when there was nothing selected. 1480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Change the selection from the "pressed" state to the 1481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the "selected" state. We treat short-press and 1482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // long-press the same here because nothing was selected. 1483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check the duration to determine if this was a short press 1489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (duration < ViewConfiguration.getLongPressTimeout()) { 1490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchViews(true /* trackball */); 1491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 1493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project performLongClick(); 1495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 1497ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// case KeyEvent.KEYCODE_BACK: 1498ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// if (event.isTracking() && !event.isCanceled()) { 1499ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mPopup.dismiss(); 1500ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.finish(); 1501ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// return true; 1502ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// } 1503ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// break; 1504146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1505146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyUp(keyCode, event); 1506146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1508146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 1509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 1510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_HIDDEN) { 1511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT 1512146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_UP 1513146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { 1514146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Display the selection box but don't move or select it 1515146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on this key press. 1516146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1517146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1518146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1519146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 1520146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Display the selection box but don't select it 1521146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // on this key press. 1522146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_PRESSED; 1523146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1524146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_SELECTED; 1529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 1530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean redraw; 1531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectionDay = mSelectionDay; 1532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (keyCode) { 153446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DEL: 153546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Delete the selected event, if any 153646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan Event selectedEvent = mSelectedEvent; 153746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (selectedEvent == null) { 153846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return false; 153946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 154046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mPopup.dismiss(); 154146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 1542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 154346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan long begin = selectedEvent.startMillis; 154446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan long end = selectedEvent.endMillis; 154546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan long id = selectedEvent.id; 154646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mDeleteEventHelper.delete(begin, end, id, -1); 1547b10f5762d0e50bac6ba31ec332e7513869b55bf3Michael Chan return true; 154846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_ENTER: 154946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan switchViews(true /* trackball or keyboard */); 155046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 155146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_BACK: 155246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (event.getRepeatCount() == 0) { 155346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan event.startTracking(); 155446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 155546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 155646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return super.onKeyDown(keyCode, event); 155746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_LEFT: 155846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 1559989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(mSelectedEvent.nextLeft); 156046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 156146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 156246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 156346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan selectionDay -= 1; 156446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 156546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 156646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 156846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_RIGHT: 156946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 1570989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(mSelectedEvent.nextRight); 157146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 157246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 157346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 157446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan selectionDay += 1; 157546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 157646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 157746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 157946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_UP: 158046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 1581989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(mSelectedEvent.nextUp); 1582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 158346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 158446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 15852fda24534978f55711526dbde747aa50d68dec40RoboErik if (!mSelectionAllday) { 1586989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(mSelectionHour - 1); 158746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan adjustHourSelection(); 158846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvents.clear(); 158946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mComputeSelectedEvents = true; 159046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 159146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 159246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 159346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 159546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case KeyEvent.KEYCODE_DPAD_DOWN: 159646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent != null) { 1597989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(mSelectedEvent.nextDown); 1598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 159946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mSelectedEvent == null) { 160046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mLastPopupEventID = INVALID_EVENT_ID; 16012fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSelectionAllday) { 16022fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = false; 160346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 1604989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(mSelectionHour + 1); 160546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan adjustHourSelection(); 160646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mSelectedEvents.clear(); 160746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mComputeSelectedEvents = true; 160846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 160946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 161046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan redraw = true; 161146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan break; 1612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 161346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan default: 161446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return super.onKeyDown(keyCode, event); 1615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((selectionDay < mFirstJulianDay) || (selectionDay > mLastJulianDay)) { 1618d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getNextView(); 1619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time date = view.mBaseDate; 1620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.set(mBaseDate); 1621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (selectionDay < mFirstJulianDay) { 1622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay -= mNumDays; 1623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 1624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay += mNumDays; 1625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.normalize(true /* ignore isDst */); 1627989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson view.setSelectedDay(selectionDay); 1628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initView(view); 163083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 163183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time end = new Time(date); 163283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan end.monthDay += mNumDays - 1; 16333458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan mController.sendEvent(this, EventType.GO_TO, date, end, -1, ViewType.CURRENT); 1634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 163604b288958078f8b29870dcbb2239df448c559610Erik if (mSelectionDay != selectionDay) { 163704b288958078f8b29870dcbb2239df448c559610Erik Time date = new Time(mBaseDate); 163804b288958078f8b29870dcbb2239df448c559610Erik date.setJulianDay(selectionDay); 163904b288958078f8b29870dcbb2239df448c559610Erik date.hour = mSelectionHour; 164004b288958078f8b29870dcbb2239df448c559610Erik mController.sendEvent(this, EventType.GO_TO, date, date, -1, ViewType.CURRENT); 164104b288958078f8b29870dcbb2239df448c559610Erik } 1642989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedDay(selectionDay); 1643146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1644146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 16458307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik mUpdateToast = true; 1646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1647146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (redraw) { 1648146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 1649146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 1650146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1652146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return super.onKeyDown(keyCode, event); 1653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1654146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 16559ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 16569ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan @Override 16579ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan public boolean onHoverEvent(MotionEvent event) { 16589ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) { 16599ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan int action = event.getAction(); 16609ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan switch (action) { 16619ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan case MotionEvent.ACTION_HOVER_ENTER: 16629ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan Log.e(TAG, "ACTION_HOVER_ENTER"); 16639ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan break; 16649ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan case MotionEvent.ACTION_HOVER_MOVE: 16659ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan Log.e(TAG, "ACTION_HOVER_MOVE"); 16669ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan break; 16679ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan case MotionEvent.ACTION_HOVER_EXIT: 16689ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan Log.e(TAG, "ACTION_HOVER_EXIT"); 16699ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan break; 16709ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan default: 16719ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan Log.e(TAG, "Unknown hover event action. " + event); 16729ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 16739ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 16749ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 16759ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan // Mouse also generates hover events 16769ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan // Send accessibility events if accessibility and exploration are on. 16779ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (!mTouchExplorationEnabled) { 16789ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan return super.onHoverEvent(event); 1679259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1680989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson if (event.getAction() != MotionEvent.ACTION_HOVER_EXIT) { 1681989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectionFromPosition((int) event.getX(), (int) event.getY(), true); 16829ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan invalidate(); 16839ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 16849ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan return true; 1685259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1686259b8f9a21fffd3858218581e9daaf689b6b888fErik 16879ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan private boolean isTouchExplorationEnabled() { 1688aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan return mIsAccessibilityEnabled && mAccessibilityMgr.isTouchExplorationEnabled(); 16899ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 1690259b8f9a21fffd3858218581e9daaf689b6b888fErik 1691aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan private void sendAccessibilityEventAsNeeded(boolean speakEvents) { 1692aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (!mIsAccessibilityEnabled) { 1693be569a176153e0b4b4606a022ab30cf2f5bf719dRoboErik return; 1694be569a176153e0b4b4606a022ab30cf2f5bf719dRoboErik } 1695989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson boolean dayChanged = mLastSelectionDayForAccessibility != mSelectionDayForAccessibility; 1696989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson boolean hourChanged = mLastSelectionHourForAccessibility != mSelectionHourForAccessibility; 1697989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson if (dayChanged || hourChanged || 1698989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mLastSelectedEventForAccessibility != mSelectedEventForAccessibility) { 1699989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mLastSelectionDayForAccessibility = mSelectionDayForAccessibility; 1700989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mLastSelectionHourForAccessibility = mSelectionHourForAccessibility; 1701989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mLastSelectedEventForAccessibility = mSelectedEventForAccessibility; 17029ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 17039ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan StringBuilder b = new StringBuilder(); 17049ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 17059ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan // Announce only the changes i.e. day or hour or both 17069ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (dayChanged) { 1707989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson b.append(getSelectedTimeForAccessibility().format("%A ")); 17089ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 17099ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (hourChanged) { 1710989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson b.append(getSelectedTimeForAccessibility().format(mIs24HourFormat ? "%k" : "%l%p")); 17119ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 1712aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (dayChanged || hourChanged) { 1713aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan b.append(PERIOD_SPACE); 1714aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 17159ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 1716aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (speakEvents) { 1717aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (mEventCountTemplate == null) { 1718aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mEventCountTemplate = mContext.getString(R.string.template_announce_item_index); 1719aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 1720aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan 1721aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan // Read out the relevant event(s) 1722aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan int numEvents = mSelectedEvents.size(); 1723aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (numEvents > 0) { 1724989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson if (mSelectedEventForAccessibility == null) { 1725aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan // Read out all the events 1726aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan int i = 1; 1727aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan for (Event calEvent : mSelectedEvents) { 1728aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (numEvents > 1) { 1729aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan // Read out x of numEvents if there are more than one event 1730aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan mStringBuilder.setLength(0); 1731aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan b.append(mFormatter.format(mEventCountTemplate, i++, numEvents)); 1732aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan b.append(" "); 1733aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 1734aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan appendEventAccessibilityString(b, calEvent); 1735aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 1736aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } else { 17379ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (numEvents > 1) { 17389ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan // Read out x of numEvents if there are more than one event 17399ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan mStringBuilder.setLength(0); 1740aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan b.append(mFormatter.format(mEventCountTemplate, mSelectedEvents 1741989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson .indexOf(mSelectedEventForAccessibility) + 1, numEvents)); 17429ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan b.append(" "); 17439ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 1744989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson appendEventAccessibilityString(b, mSelectedEventForAccessibility); 1745259b8f9a21fffd3858218581e9daaf689b6b888fErik } 17469ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } else { 1747aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan b.append(mCreateNewEventString); 1748259b8f9a21fffd3858218581e9daaf689b6b888fErik } 17499ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 17509ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 1751aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan if (dayChanged || hourChanged || speakEvents) { 1752aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan AccessibilityEvent event = AccessibilityEvent 1753d01a7b6aab2bfe79e60359137d1bfd7ec9672368Michael Chan .obtain(AccessibilityEvent.TYPE_VIEW_FOCUSED); 1754aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan CharSequence msg = b.toString(); 1755aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan event.getText().add(msg); 1756aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan event.setAddedCount(msg.length()); 1757aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan sendAccessibilityEventUnchecked(event); 1758aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan } 1759259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1760259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1761259b8f9a21fffd3858218581e9daaf689b6b888fErik 1762259b8f9a21fffd3858218581e9daaf689b6b888fErik /** 1763259b8f9a21fffd3858218581e9daaf689b6b888fErik * @param b 1764259b8f9a21fffd3858218581e9daaf689b6b888fErik * @param calEvent 1765259b8f9a21fffd3858218581e9daaf689b6b888fErik */ 1766259b8f9a21fffd3858218581e9daaf689b6b888fErik private void appendEventAccessibilityString(StringBuilder b, Event calEvent) { 1767259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(calEvent.getTitleAndLocation()); 1768259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(PERIOD_SPACE); 1769259b8f9a21fffd3858218581e9daaf689b6b888fErik String when; 1770259b8f9a21fffd3858218581e9daaf689b6b888fErik int flags = DateUtils.FORMAT_SHOW_DATE; 1771259b8f9a21fffd3858218581e9daaf689b6b888fErik if (calEvent.allDay) { 1772259b8f9a21fffd3858218581e9daaf689b6b888fErik flags |= DateUtils.FORMAT_UTC | DateUtils.FORMAT_SHOW_WEEKDAY; 1773259b8f9a21fffd3858218581e9daaf689b6b888fErik } else { 1774259b8f9a21fffd3858218581e9daaf689b6b888fErik flags |= DateUtils.FORMAT_SHOW_TIME; 1775259b8f9a21fffd3858218581e9daaf689b6b888fErik if (DateFormat.is24HourFormat(mContext)) { 1776259b8f9a21fffd3858218581e9daaf689b6b888fErik flags |= DateUtils.FORMAT_24HOUR; 1777259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1778259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1779259b8f9a21fffd3858218581e9daaf689b6b888fErik when = Utils.formatDateRange(mContext, calEvent.startMillis, calEvent.endMillis, flags); 1780259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(when); 1781259b8f9a21fffd3858218581e9daaf689b6b888fErik b.append(PERIOD_SPACE); 1782259b8f9a21fffd3858218581e9daaf689b6b888fErik } 1783259b8f9a21fffd3858218581e9daaf689b6b888fErik 17846d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private class GotoBroadcaster implements Animation.AnimationListener { 17856d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private final int mCounter; 17866d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private final Time mStart; 17876d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan private final Time mEnd; 17886d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 17896d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public GotoBroadcaster(Time start, Time end) { 17906d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan mCounter = ++sCounter; 17916d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan mStart = start; 17926d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan mEnd = end; 17936d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 17946d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 17956d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan @Override 17966d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public void onAnimationEnd(Animation animation) { 1797f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan DayView view = (DayView) mViewSwitcher.getCurrentView(); 1798f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan view.mViewStartX = 0; 1799f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan view = (DayView) mViewSwitcher.getNextView(); 1800f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan view.mViewStartX = 0; 1801f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan 18026d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (mCounter == sCounter) { 1803f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mController.sendEvent(this, EventType.GO_TO, mStart, mEnd, null, -1, 1804f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan ViewType.CURRENT, CalendarController.EXTRA_GOTO_DATE, null, null); 18056d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 18066d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 18076d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 18086d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan @Override 18096d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public void onAnimationRepeat(Animation animation) { 18106d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 18116d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 18126d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan @Override 18136d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan public void onAnimationStart(Animation animation) { 18146d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 18156d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 18166d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 18172c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan private View switchViews(boolean forward, float xOffSet, float width, float velocity) { 181895d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan mAnimationDistance = width - xOffSet; 181995d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan if (DEBUG) { 182095d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan Log.d(TAG, "switchViews(" + forward + ") O:" + xOffSet + " Dist:" + mAnimationDistance); 182195d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan } 182295d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan 1823ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float progress = Math.abs(xOffSet) / width; 1824ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (progress > 1.0f) { 1825ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan progress = 1.0f; 1826ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1827ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1828ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float inFromXValue, inToXValue; 1829ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan float outFromXValue, outToXValue; 1830ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (forward) { 1831ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inFromXValue = 1.0f - progress; 1832ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inToXValue = 0.0f; 1833ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outFromXValue = -progress; 1834ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outToXValue = -1.0f; 1835ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } else { 1836ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inFromXValue = progress - 1.0f; 1837ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inToXValue = 0.0f; 1838ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outFromXValue = progress; 1839ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outToXValue = 1.0f; 1840ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1841ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 18426d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan final Time start = new Time(mBaseDate.timezone); 18436d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan start.set(mController.getTime()); 18446d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (forward) { 18456d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan start.monthDay += mNumDays; 18466d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } else { 18476d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan start.monthDay -= mNumDays; 18486d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 1849f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mController.setTime(start.normalize(true)); 1850f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan 1851f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Time newSelected = start; 18526d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 18536d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan if (mNumDays == 7) { 1854f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan newSelected = new Time(start); 18556d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan adjustToBeginningOfWeek(start); 18566d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 18576d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 18586d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan final Time end = new Time(start); 18596d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan end.monthDay += mNumDays - 1; 18606d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 1861ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // We have to allocate these animation objects each time we switch views 1862ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan // because that is the only way to set the animation parameters. 1863ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan TranslateAnimation inAnimation = new TranslateAnimation( 1864ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, inFromXValue, 1865ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, inToXValue, 1866ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f, 1867ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f); 1868ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1869ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan TranslateAnimation outAnimation = new TranslateAnimation( 1870ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, outFromXValue, 1871ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.RELATIVE_TO_SELF, outToXValue, 1872ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f, 1873ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan Animation.ABSOLUTE, 0.0f); 1874ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 18752c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan long duration = calculateDuration(width - Math.abs(xOffSet), width, velocity); 1876ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan inAnimation.setDuration(duration); 18772c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan inAnimation.setInterpolator(mHScrollInterpolator); 18782c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan outAnimation.setInterpolator(mHScrollInterpolator); 1879ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan outAnimation.setDuration(duration); 18806d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan outAnimation.setAnimationListener(new GotoBroadcaster(start, end)); 1881ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.setInAnimation(inAnimation); 1882ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.setOutAnimation(outAnimation); 1883ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1884d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getCurrentView(); 1885ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.cleanup(); 1886ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan mViewSwitcher.showNext(); 1887d190418220467c02327dd9b3ae1eae238889720bMichael Chan view = (DayView) mViewSwitcher.getCurrentView(); 18885b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik view.setSelected(newSelected, true, false); 1889ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.requestFocus(); 1890ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan view.reloadEvents(); 1891eaafa2b48be7194a61754604ae37b3d62e9118d8Erik view.updateTitle(); 189258f5055e1f3740382b4507e6eb88eebc2d6c21c1Michael Chan view.restartCurrentTimeUpdates(); 1893e98dd73c67205b01f5348271d9a7a630003ecf52David Brown 1894ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return view; 1895ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 1896ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 1897146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This is called after scrolling stops to move the selected hour 1898146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // to the visible part of the screen. 1899146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void resetSelectedHour() { 1900146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < mFirstHour + 1) { 1901989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(mFirstHour + 1); 1902989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(null); 1903146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1904146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1905146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionHour > mFirstHour + mNumHours - 3) { 1906989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(mFirstHour + mNumHours - 3); 1907989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(null); 1908146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 1909146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 1910146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1911146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1912146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1913146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void initFirstHour() { 1914d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mFirstHour = mSelectionHour - mNumHours / 5; 1915146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 0) { 1916146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = 0; 1917146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mFirstHour + mNumHours > 24) { 1918146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = 24 - mNumHours; 1919146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1920146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1921146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1922146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 1923146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Recomputes the first full hour that is visible on screen after the 1924146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * screen is scrolled. 1925146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 1926146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeFirstHour() { 1927146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the first full hour that is visible on screen 1928146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour = (mViewStartY + mCellHeight + HOUR_GAP - 1) / (mCellHeight + HOUR_GAP); 1929146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHourOffset = mFirstHour * (mCellHeight + HOUR_GAP) - mViewStartY; 1930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1932146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void adjustHourSelection() { 1933146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < 0) { 1934989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(0); 19352fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > 0) { 1936146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 19372fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = true; 1938146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1939146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1940146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1941146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour > 23) { 1942989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(23); 1943146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1944146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1945146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the selected hour is at least 2 time slots from the top and 1946146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // bottom of the screen, then don't scroll the view. 1947146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour < mFirstHour + 1) { 1948146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there are all-days events for the selected day but there 1949146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // are no more normal events earlier in the day, then jump to 1950146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the all-day event area. 1951146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Exception 1: allow the user to scroll to 8am with the trackball 1952146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // before jumping to the all-day event area. 1953146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Exception 2: if 12am is on screen, then allow the user to select 1954146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // 12am before going up to the all-day event area. 1955146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 19562fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > 0 && mEarliestStartHour[daynum] > mSelectionHour 1957146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && mFirstHour > 0 && mFirstHour < 8) { 1958146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 19592fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = true; 1960989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(mFirstHour + 1); 1961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1964146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour > 0) { 1965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour -= 1; 1966146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY -= (mCellHeight + HOUR_GAP); 1967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 1968146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 1969146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1970146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1971146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1972146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1973146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1974146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionHour > mFirstHour + mNumHours - 3) { 1975146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 24 - mNumHours) { 1976146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mFirstHour += 1; 1977146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY += (mCellHeight + HOUR_GAP); 1978c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik if (mViewStartY > mMaxViewStartY) { 1979c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mViewStartY = mMaxViewStartY; 1980146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1981146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 1982146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mFirstHour == 24 - mNumHours && mFirstHourOffset > 0) { 1983c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik mViewStartY = mMaxViewStartY; 1984146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1985146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1986146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1987146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1988146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project void clearCachedEvents() { 1989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastReloadMillis = 0; 1990146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1991146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 1992056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Runnable mCancelCallback = new Runnable() { 1993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 1994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project clearCachedEvents(); 1995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 1996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }; 1997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 199846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa /* package */ void reloadEvents() { 1999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against this being called before this view has been 2000146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // initialized. 2001ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// if (mContext == null) { 2002ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// return; 2003ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// } 2004146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2005731f1cb808b7586b93615b408ab2636081fab0dcErik // Make sure our time zones are up to date 2006731f1cb808b7586b93615b408ab2636081fab0dcErik mTZUpdater.run(); 2007731f1cb808b7586b93615b408ab2636081fab0dcErik 2008989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(null); 2009146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 2010146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 2011146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2012146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The start date is the beginning of the week at 12am 2013731f1cb808b7586b93615b408ab2636081fab0dcErik Time weekStart = new Time(Utils.getTimeZone(mContext, mTZUpdater)); 2014146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.set(mBaseDate); 2015146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.hour = 0; 2016146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.minute = 0; 2017146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project weekStart.second = 0; 2018146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long millis = weekStart.normalize(true /* ignore isDst */); 2019146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2020146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Avoid reloading events unnecessarily. 2021146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (millis == mLastReloadMillis) { 2022146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 2023146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2024146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mLastReloadMillis = millis; 2025146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2026146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // load events in the background 2027ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan// mContext.startProgressSpinner(); 2028146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final ArrayList<Event> events = new ArrayList<Event>(); 2029b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik mEventLoader.loadEventsInBackground(mNumDays, events, mFirstJulianDay, new Runnable() { 2030146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 20311662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson boolean fadeinEvents = mFirstJulianDay != mLoadedFirstJulianDay; 2032146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mEvents = events; 20331662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson mLoadedFirstJulianDay = mFirstJulianDay; 203408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mAllDayEvents == null) { 203508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents = new ArrayList<Event>(); 203608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 203708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents.clear(); 203808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 203908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 204008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Create a shorter array for all day events 204146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan for (Event e : events) { 204268655b5af2b7e5f872a103858ec58a19042123ceRoboErik if (e.drawAsAllday()) { 204308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayEvents.add(e); 204408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 204508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 204608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 204708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // New events, new layouts 204808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mLayouts == null || mLayouts.length < events.size()) { 204908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mLayouts = new StaticLayout[events.size()]; 205008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 205108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Arrays.fill(mLayouts, null); 20523e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 205308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 205408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (mAllDayLayouts == null || mAllDayLayouts.length < mAllDayEvents.size()) { 205508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan mAllDayLayouts = new StaticLayout[events.size()]; 205608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 205708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Arrays.fill(mAllDayLayouts, null); 205808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 205908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 20602fda24534978f55711526dbde747aa50d68dec40RoboErik computeEventRelations(); 20612fda24534978f55711526dbde747aa50d68dec40RoboErik 2062146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = true; 2063146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = true; 2064146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project recalc(); 20650a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson 20660a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson // Start animation to cross fade the events 20671662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson if (fadeinEvents) { 20681662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson if (mEventsCrossFadeAnimation == null) { 20691662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson mEventsCrossFadeAnimation = 20701662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson ObjectAnimator.ofInt(DayView.this, "EventsAlpha", 0, 255); 20711662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson mEventsCrossFadeAnimation.setDuration(EVENTS_CROSS_FADE_DURATION); 20721662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson } 20731662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson mEventsCrossFadeAnimation.start(); 20741662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson } else{ 20751662b85ef3691df66820fd2a469bcb95993c14a5Isaac Katzenelson invalidate(); 20760a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson } 2077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2078146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project }, mCancelCallback); 2079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2080146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 20810a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson public void setEventsAlpha(int alpha) { 20820a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson mEventsAlpha = alpha; 20830a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson invalidate(); 20840a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson } 20850a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson 20860a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson public int getEventsAlpha() { 20870a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson return mEventsAlpha; 20880a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson } 20890a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson 20900a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson public void stopEventsAnimation() { 20910a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson if (mEventsCrossFadeAnimation != null) { 20920a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson mEventsCrossFadeAnimation.cancel(); 20930a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson } 20940a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson mEventsAlpha = 255; 20950a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson } 20960a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson 20972fda24534978f55711526dbde747aa50d68dec40RoboErik private void computeEventRelations() { 20982fda24534978f55711526dbde747aa50d68dec40RoboErik // Compute the layout relation between each event before measuring cell 20992fda24534978f55711526dbde747aa50d68dec40RoboErik // width, as the cell width should be adjusted along with the relation. 21002fda24534978f55711526dbde747aa50d68dec40RoboErik // 21012fda24534978f55711526dbde747aa50d68dec40RoboErik // Examples: A (1:00pm - 1:01pm), B (1:02pm - 2:00pm) 21022fda24534978f55711526dbde747aa50d68dec40RoboErik // We should mark them as "overwapped". Though they are not overwapped logically, but 21032fda24534978f55711526dbde747aa50d68dec40RoboErik // minimum cell height implicitly expands the cell height of A and it should look like 21042fda24534978f55711526dbde747aa50d68dec40RoboErik // (1:00pm - 1:15pm) after the cell height adjustment. 21052fda24534978f55711526dbde747aa50d68dec40RoboErik 21062fda24534978f55711526dbde747aa50d68dec40RoboErik // Compute the space needed for the all-day events, if any. 21072fda24534978f55711526dbde747aa50d68dec40RoboErik // Make a pass over all the events, and keep track of the maximum 21082fda24534978f55711526dbde747aa50d68dec40RoboErik // number of all-day events in any one day. Also, keep track of 21092fda24534978f55711526dbde747aa50d68dec40RoboErik // the earliest event in each day. 21102fda24534978f55711526dbde747aa50d68dec40RoboErik int maxAllDayEvents = 0; 21112fda24534978f55711526dbde747aa50d68dec40RoboErik final ArrayList<Event> events = mEvents; 21122fda24534978f55711526dbde747aa50d68dec40RoboErik final int len = events.size(); 21132fda24534978f55711526dbde747aa50d68dec40RoboErik // Num of all-day-events on each day. 21142fda24534978f55711526dbde747aa50d68dec40RoboErik final int eventsCount[] = new int[mLastJulianDay - mFirstJulianDay + 1]; 21152fda24534978f55711526dbde747aa50d68dec40RoboErik Arrays.fill(eventsCount, 0); 21162fda24534978f55711526dbde747aa50d68dec40RoboErik for (int ii = 0; ii < len; ii++) { 21172fda24534978f55711526dbde747aa50d68dec40RoboErik Event event = events.get(ii); 21182fda24534978f55711526dbde747aa50d68dec40RoboErik if (event.startDay > mLastJulianDay || event.endDay < mFirstJulianDay) { 21192fda24534978f55711526dbde747aa50d68dec40RoboErik continue; 21202fda24534978f55711526dbde747aa50d68dec40RoboErik } 21212fda24534978f55711526dbde747aa50d68dec40RoboErik if (event.drawAsAllday()) { 21222fda24534978f55711526dbde747aa50d68dec40RoboErik // Count all the events being drawn as allDay events 21232fda24534978f55711526dbde747aa50d68dec40RoboErik final int firstDay = Math.max(event.startDay, mFirstJulianDay); 21242fda24534978f55711526dbde747aa50d68dec40RoboErik final int lastDay = Math.min(event.endDay, mLastJulianDay); 21252fda24534978f55711526dbde747aa50d68dec40RoboErik for (int day = firstDay; day <= lastDay; day++) { 21262fda24534978f55711526dbde747aa50d68dec40RoboErik final int count = ++eventsCount[day - mFirstJulianDay]; 21272fda24534978f55711526dbde747aa50d68dec40RoboErik if (maxAllDayEvents < count) { 21282fda24534978f55711526dbde747aa50d68dec40RoboErik maxAllDayEvents = count; 21292fda24534978f55711526dbde747aa50d68dec40RoboErik } 21302fda24534978f55711526dbde747aa50d68dec40RoboErik } 21312fda24534978f55711526dbde747aa50d68dec40RoboErik 21322fda24534978f55711526dbde747aa50d68dec40RoboErik int daynum = event.startDay - mFirstJulianDay; 21332fda24534978f55711526dbde747aa50d68dec40RoboErik int durationDays = event.endDay - event.startDay + 1; 21342fda24534978f55711526dbde747aa50d68dec40RoboErik if (daynum < 0) { 21352fda24534978f55711526dbde747aa50d68dec40RoboErik durationDays += daynum; 21362fda24534978f55711526dbde747aa50d68dec40RoboErik daynum = 0; 21372fda24534978f55711526dbde747aa50d68dec40RoboErik } 21382fda24534978f55711526dbde747aa50d68dec40RoboErik if (daynum + durationDays > mNumDays) { 21392fda24534978f55711526dbde747aa50d68dec40RoboErik durationDays = mNumDays - daynum; 21402fda24534978f55711526dbde747aa50d68dec40RoboErik } 21412fda24534978f55711526dbde747aa50d68dec40RoboErik for (int day = daynum; durationDays > 0; day++, durationDays--) { 21422fda24534978f55711526dbde747aa50d68dec40RoboErik mHasAllDayEvent[day] = true; 21432fda24534978f55711526dbde747aa50d68dec40RoboErik } 21442fda24534978f55711526dbde747aa50d68dec40RoboErik } else { 21452fda24534978f55711526dbde747aa50d68dec40RoboErik int daynum = event.startDay - mFirstJulianDay; 21462fda24534978f55711526dbde747aa50d68dec40RoboErik int hour = event.startTime / 60; 21472fda24534978f55711526dbde747aa50d68dec40RoboErik if (daynum >= 0 && hour < mEarliestStartHour[daynum]) { 21482fda24534978f55711526dbde747aa50d68dec40RoboErik mEarliestStartHour[daynum] = hour; 21492fda24534978f55711526dbde747aa50d68dec40RoboErik } 21502fda24534978f55711526dbde747aa50d68dec40RoboErik 21512fda24534978f55711526dbde747aa50d68dec40RoboErik // Also check the end hour in case the event spans more than 21522fda24534978f55711526dbde747aa50d68dec40RoboErik // one day. 21532fda24534978f55711526dbde747aa50d68dec40RoboErik daynum = event.endDay - mFirstJulianDay; 21542fda24534978f55711526dbde747aa50d68dec40RoboErik hour = event.endTime / 60; 21552fda24534978f55711526dbde747aa50d68dec40RoboErik if (daynum < mNumDays && hour < mEarliestStartHour[daynum]) { 21562fda24534978f55711526dbde747aa50d68dec40RoboErik mEarliestStartHour[daynum] = hour; 21572fda24534978f55711526dbde747aa50d68dec40RoboErik } 21582fda24534978f55711526dbde747aa50d68dec40RoboErik } 21592fda24534978f55711526dbde747aa50d68dec40RoboErik } 21602fda24534978f55711526dbde747aa50d68dec40RoboErik mMaxAlldayEvents = maxAllDayEvents; 21612fda24534978f55711526dbde747aa50d68dec40RoboErik initAllDayHeights(); 21622fda24534978f55711526dbde747aa50d68dec40RoboErik } 21632fda24534978f55711526dbde747aa50d68dec40RoboErik 2164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 2165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project protected void onDraw(Canvas canvas) { 2166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mRemeasure) { 2167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project remeasure(getWidth(), getHeight()); 2168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mRemeasure = false; 2169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2170c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.save(); 2171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 21722fda24534978f55711526dbde747aa50d68dec40RoboErik float yTranslate = -mViewStartY + DAY_HEADER_HEIGHT + mAlldayHeight; 2173c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // offset canvas by the current drag and header position 2174c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(-mViewStartX, yTranslate); 2175c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // clip to everything below the allDay area 2176c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik Rect dest = mDestRect; 2177c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.top = (int) (mFirstCell - yTranslate); 2178c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.bottom = (int) (mViewHeight - yTranslate); 2179c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.left = 0; 2180c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik dest.right = mViewWidth; 2181c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.save(); 2182c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.clipRect(dest); 2183c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Draw the movable part of the view 2184c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik doDraw(canvas); 2185c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // restore to having no clip 2186c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.restore(); 2187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 2189c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik float xTranslate; 2190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartX > 0) { 2191c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik xTranslate = mViewWidth; 2192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2193c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik xTranslate = -mViewWidth; 2194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2195c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Move the canvas around to prep it for the next view 2196c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // specifically, shift it by a screen and undo the 2197c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // yTranslation which will be redone in the nextView's onDraw(). 2198c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(xTranslate, -yTranslate); 2199d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView nextView = (DayView) mViewSwitcher.getNextView(); 2200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Prevent infinite recursive calls to onDraw(). 2202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project nextView.mTouchMode = TOUCH_MODE_INITIAL_STATE; 2203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project nextView.onDraw(canvas); 2205c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // Move it back for this view 2206c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(-xTranslate, 0); 2207c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik } else { 2208c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // If we drew another view we already translated it back 2209c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // If we didn't draw another view we should be at the edge of the 2210c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik // screen 2211c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik canvas.translate(mViewStartX, -yTranslate); 2212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the fixed areas (that don't scroll) directly to the canvas. 2215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAfterScroll(canvas); 22168307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik if (mComputeSelectedEvents && mUpdateToast) { 22178307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik updateEventDetails(); 22188307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik mUpdateToast = false; 22198307109ac75b748ae707f4d4cb9a9d28c2dbaae6Erik } 2220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mComputeSelectedEvents = false; 2221433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 2222433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // Draw overscroll glow 2223433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (!mEdgeEffectTop.isFinished()) { 2224433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (DAY_HEADER_HEIGHT != 0) { 2225433ba924de1ac26b923e2beb061812012749e4f3Michael Chan canvas.translate(0, DAY_HEADER_HEIGHT); 2226433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2227433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mEdgeEffectTop.draw(canvas)) { 2228433ba924de1ac26b923e2beb061812012749e4f3Michael Chan invalidate(); 2229433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2230433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (DAY_HEADER_HEIGHT != 0) { 2231433ba924de1ac26b923e2beb061812012749e4f3Michael Chan canvas.translate(0, -DAY_HEADER_HEIGHT); 2232433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2233433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2234433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (!mEdgeEffectBottom.isFinished()) { 2235433ba924de1ac26b923e2beb061812012749e4f3Michael Chan canvas.rotate(180, mViewWidth/2, mViewHeight/2); 2236433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mEdgeEffectBottom.draw(canvas)) { 2237433ba924de1ac26b923e2beb061812012749e4f3Michael Chan invalidate(); 2238433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2239433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 2240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project canvas.restore(); 2241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAfterScroll(Canvas canvas) { 2244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mPaint; 2245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r = mRect; 2246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2247e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik drawAllDayHighlights(r, canvas, p); 22482fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents != 0) { 22491ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan drawAllDayEvents(mFirstJulianDay, mNumDays, canvas, p); 22508f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan drawUpperLeftCorner(r, canvas, p); 2251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2253c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik drawScrollLine(r, canvas, p); 22543eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan drawDayHeaderLoop(r, canvas, p); 2255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the AM and PM indicators if we're in 12 hour mode 2257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!mIs24HourFormat) { 2258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawAmPm(canvas, p); 2259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 226246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // This isn't really the upper-left corner. It's the square area just 2263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // below the upper-left corner, above the hours and to the left of the 2264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // all-day area. 22658f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private void drawUpperLeftCorner(Rect r, Canvas canvas, Paint p) { 22668f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan setupHourTextPaint(p); 22672fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount) { 2268cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik // Draw the allDay expand/collapse icon 2269cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik if (mUseExpandIcon) { 2270cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mExpandAlldayDrawable.setBounds(mExpandAllDayRect); 2271cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mExpandAlldayDrawable.draw(canvas); 2272cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik } else { 2273cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mCollapseAlldayDrawable.setBounds(mExpandAllDayRect); 2274cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mCollapseAlldayDrawable.draw(canvas); 2275cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik } 22762fda24534978f55711526dbde747aa50d68dec40RoboErik } 22778f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan } 2278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2279c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik private void drawScrollLine(Rect r, Canvas canvas, Paint p) { 2280b03348cec4c175846f074a656db5c121d5467e2dMichael Chan final int right = computeDayLeftPosition(mNumDays); 22818f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan final int y = mFirstCell - 1; 22828f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan 2283c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(false); 22848f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setStyle(Style.FILL); 22858f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan 22868f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setColor(mCalendarGridLineInnerHorizontalColor); 22878f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 22888f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawLine(GRID_LINE_LEFT_MARGIN, y, right, y, p); 2289c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik p.setAntiAlias(true); 2290c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik } 2291c29b2d3342d43c2662dd2fe51a28bc7e8acd7b36Erik 2292b03348cec4c175846f074a656db5c121d5467e2dMichael Chan // Computes the x position for the left side of the given day (base 0) 2293e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private int computeDayLeftPosition(int day) { 2294e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int effectiveWidth = mViewWidth - mHoursWidth; 2295e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik return day * effectiveWidth / mNumDays + mHoursWidth; 2296e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2297e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 2298e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private void drawAllDayHighlights(Rect r, Canvas canvas, Paint p) { 2299cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan if (mFutureBgColor != 0) { 2300cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan // First, color the labels area light gray 2301e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.top = 0; 2302cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.bottom = DAY_HEADER_HEIGHT; 2303cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.left = 0; 2304cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.right = mViewWidth; 2305cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan p.setColor(mBgColor); 2306e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setStyle(Style.FILL); 2307e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik canvas.drawRect(r, p); 2308cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan // and the area that says All day 2309cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.top = DAY_HEADER_HEIGHT; 2310cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.bottom = mFirstCell - 1; 2311cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.left = 0; 2312cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.right = mHoursWidth; 2313cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan canvas.drawRect(r, p); 2314cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan 2315cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan int startIndex = -1; 2316cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan 2317cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan int todayIndex = mTodayJulianDay - mFirstJulianDay; 2318cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan if (todayIndex < 0) { 2319cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan // Future 2320cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan startIndex = 0; 2321cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } else if (todayIndex >= 1 && todayIndex + 1 < mNumDays) { 2322cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan // Multiday - tomorrow is visible. 2323cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan startIndex = todayIndex + 1; 2324cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } 2325cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan 2326cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan if (startIndex >= 0) { 2327cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan // Draw the future highlight 2328cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.top = 0; 2329cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.bottom = mFirstCell - 1; 2330cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan r.left = computeDayLeftPosition(startIndex) + 1; 2331b03348cec4c175846f074a656db5c121d5467e2dMichael Chan r.right = computeDayLeftPosition(mNumDays); 2332cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan p.setColor(mFutureBgColor); 2333cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan p.setStyle(Style.FILL); 2334cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan canvas.drawRect(r, p); 2335cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } 2336e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 233721bd42039c92232647f54461cd20708224cc7eb6Michael Chan 2338b6fb51224b578b26e503fddae2799d03a2aaad47RoboErik if (mSelectionAllday && mSelectionMode != SELECTION_HIDDEN) { 2339e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik // Draw the selection highlight on the selected all-day area 2340e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mRect.top = DAY_HEADER_HEIGHT + 1; 2341e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mRect.bottom = mRect.top + mAlldayHeight + ALLDAY_TOP_MARGIN - 2; 2342e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int daynum = mSelectionDay - mFirstJulianDay; 2343e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mRect.left = computeDayLeftPosition(daynum) + 1; 2344e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik mRect.right = computeDayLeftPosition(daynum + 1); 2345e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setColor(mCalendarGridAreaSelected); 2346e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik canvas.drawRect(mRect, p); 2347e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2348e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2349e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 2350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawDayHeaderLoop(Rect r, Canvas canvas, Paint p) { 2351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw the horizontal day background banner 23523eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarDateBannerBackground); 23533eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.top = 0; 23543eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.bottom = DAY_HEADER_HEIGHT; 23553eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = 0; 23563eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mHoursWidth + mNumDays * (mCellWidth + DAY_GAP); 23573eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 23583eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // 2359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Fill the extra space on the right side with the default background 23603eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.left = r.right; 23613eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // r.right = mViewWidth; 23623eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // p.setColor(mCalendarGridAreaBackground); 23633eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // canvas.drawRect(r, p); 2364e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik if (mNumDays == 1 && ONE_DAY_HEADER_HEIGHT == 0) { 2365e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik return; 2366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 23683eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTypeface(mBold); 23693eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextAlign(Paint.Align.RIGHT); 2370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cell = mFirstJulianDay; 2371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String[] dayNames; 2373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mDateStrWidth < mCellWidth) { 2374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dayNames = mDayStrs; 2375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dayNames = mDayStrs2Letter; 2377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2379d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setAntiAlias(true); 2380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++, cell++) { 23811f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan int dayOfWeek = day + mFirstVisibleDayOfWeek; 23821f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan if (dayOfWeek >= 14) { 23831f711ed63be864c94259a65deef8d5cdf380b9fbMichael Chan dayOfWeek -= 14; 2384487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan } 2385487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan 23863eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int color = mCalendarDateBannerTextColor; 2387071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (mNumDays == 1) { 2388071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (dayOfWeek == Time.SATURDAY) { 2389071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_saturdayColor; 2390071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else if (dayOfWeek == Time.SUNDAY) { 2391071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_sundayColor; 2392071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } 2393071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else { 2394071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa final int column = day % 7; 2395071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa if (Utils.isSaturday(column, mFirstDayOfWeek)) { 2396071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_saturdayColor; 2397071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } else if (Utils.isSunday(column, mFirstDayOfWeek)) { 2398071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa color = mWeek_sundayColor; 2399071d56d859b0c9f9c7f002e2bee98bc1bd0fc95fDaisuke Miyakawa } 24003eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 24013eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 24023eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(color); 2403e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik drawDayHeader(dayNames[dayOfWeek], day, cell, canvas, p); 2404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 24053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTypeface(null); 2406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawAmPm(Canvas canvas, Paint p) { 2409d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan p.setColor(mCalendarAmPmLabel); 2410e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextSize(AMPM_TEXT_SIZE); 2411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTypeface(mBold); 2412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 2413e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextAlign(Paint.Align.RIGHT); 2414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String text = mAmString; 2415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour >= 12) { 2416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = mPmString; 2417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = mFirstCell + mFirstHourOffset + 2 * mHoursTextHeight + HOUR_GAP; 24198f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawText(text, HOURS_LEFT_MARGIN, y, p); 2420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mFirstHour < 12 && mFirstHour + mNumHours > 12) { 2422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also draw the "PM" 2423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project text = mPmString; 2424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y = mFirstCell + mFirstHourOffset + (12 - mFirstHour) * (mCellHeight + HOUR_GAP) 2425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project + 2 * mHoursTextHeight + HOUR_GAP; 24268f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawText(text, HOURS_LEFT_MARGIN, y, p); 2427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2430e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private void drawCurrentTimeLine(Rect r, final int day, final int top, Canvas canvas, 2431f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan Paint p) { 2432e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.left = computeDayLeftPosition(day) - CURRENT_TIME_LINE_SIDE_BUFFER + 1; 2433763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.right = computeDayLeftPosition(day + 1) + CURRENT_TIME_LINE_SIDE_BUFFER + 1; 24343eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 2435763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.top = top - CURRENT_TIME_LINE_TOP_OFFSET; 24363eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan r.bottom = r.top + mCurrentTimeLine.getIntrinsicHeight(); 2437bd0e834aea317236d574f8738fe11a51fdc87968Erik 24383eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine.setBounds(r); 24393eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan mCurrentTimeLine.draw(canvas); 24405b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mAnimateToday) { 24415b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mCurrentTimeAnimateLine.setBounds(r); 24425b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mCurrentTimeAnimateLine.setAlpha(mAnimateTodayAlpha); 24435b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mCurrentTimeAnimateLine.draw(canvas); 24445b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2445bd0e834aea317236d574f8738fe11a51fdc87968Erik } 2446bd0e834aea317236d574f8738fe11a51fdc87968Erik 2447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void doDraw(Canvas canvas) { 2448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint p = mPaint; 2449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect r = mRect; 2450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2451cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan if (mFutureBgColor != 0) { 2452cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan drawBgColors(r, canvas, p); 2453cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan } 2454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawGridBackground(r, canvas, p); 2455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project drawHours(r, canvas, p); 2456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw each day 2458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cell = mFirstJulianDay; 2459e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 24600a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson int alpha = p.getAlpha(); 24610a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson p.setAlpha(mEventsAlpha); 2462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int day = 0; day < mNumDays; day++, cell++) { 246308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // TODO Wow, this needs cleanup. drawEvents loop through all the 246408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // events on every call. 2465e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik drawEvents(cell, day, HOUR_GAP, canvas, p); 246646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // If this is today 246746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (cell == mTodayJulianDay) { 24681ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int lineY = mCurrentTime.hour * (mCellHeight + HOUR_GAP) 24691ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan + ((mCurrentTime.minute * mCellHeight) / 60) + 1; 24701ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 247146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // And the current time shows up somewhere on the screen 247246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (lineY >= mViewStartY && lineY < mViewStartY + mViewHeight - 2) { 2473e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik drawCurrentTimeLine(r, day, lineY, canvas, p); 2474bd0e834aea317236d574f8738fe11a51fdc87968Erik } 2475bd0e834aea317236d574f8738fe11a51fdc87968Erik } 2476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2477e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(true); 24780a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson p.setAlpha(alpha); 2479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 248095f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan drawSelectedRect(r, canvas, p); 248195f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan } 24823eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 248395f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan private void drawSelectedRect(Rect r, Canvas canvas, Paint p) { 2484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Draw a highlight on the selected hour (if needed) 24852fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSelectionMode != SELECTION_HIDDEN && !mSelectionAllday) { 24863937a47bc5a1afb9701e1d0565fae31f5800590dErik int daynum = mSelectionDay - mFirstJulianDay; 2487ba902466b19b11d587468e354edc58e542707747Michael Chan r.top = mSelectionHour * (mCellHeight + HOUR_GAP); 24881ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top + mCellHeight + HOUR_GAP; 2489d0c06c6c8815d027c595cb70b01478634a84c8e0RoboErik r.left = computeDayLeftPosition(daynum) + 1; 2490d0c06c6c8815d027c595cb70b01478634a84c8e0RoboErik r.right = computeDayLeftPosition(daynum + 1) + 1; 2491ba902466b19b11d587468e354edc58e542707747Michael Chan 2492ba902466b19b11d587468e354edc58e542707747Michael Chan saveSelectionPosition(r.left, r.top, r.right, r.bottom); 24933937a47bc5a1afb9701e1d0565fae31f5800590dErik 249495f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan // Draw the highlight on the grid 24953937a47bc5a1afb9701e1d0565fae31f5800590dErik p.setColor(mCalendarGridAreaSelected); 24963937a47bc5a1afb9701e1d0565fae31f5800590dErik r.top += HOUR_GAP; 24973937a47bc5a1afb9701e1d0565fae31f5800590dErik r.right -= DAY_GAP; 2498e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 24993937a47bc5a1afb9701e1d0565fae31f5800590dErik canvas.drawRect(r, p); 250095f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan 2501ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson // Draw a "new event hint" on top of the highlight 2502ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson // For the week view, show a "+", for day view, show "+ New event" 2503ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setColor(mNewEventHintColor); 2504ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson if (mNumDays > 1) { 2505ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setStrokeWidth(NEW_EVENT_WIDTH); 2506ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int width = r.right - r.left; 2507ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int midX = r.left + width / 2; 2508ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int midY = r.top + mCellHeight / 2; 2509ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int length = Math.min(mCellHeight, width) - NEW_EVENT_MARGIN * 2; 2510ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson length = Math.min(length, NEW_EVENT_MAX_LENGTH); 2511ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int verticalPadding = (mCellHeight - length) / 2; 2512ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson int horizontalPadding = (width - length) / 2; 2513ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson canvas.drawLine(r.left + horizontalPadding, midY, r.right - horizontalPadding, 2514ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson midY, p); 2515ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson canvas.drawLine(midX, r.top + verticalPadding, midX, r.bottom - verticalPadding, p); 2516ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson } else { 2517ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setStyle(Paint.Style.FILL); 2518ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setTextSize(NEW_EVENT_HINT_FONT_SIZE); 2519ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setTextAlign(Paint.Align.LEFT); 2520ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson p.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); 2521ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson canvas.drawText(mNewEventHintString, r.left + EVENT_TEXT_LEFT_MARGIN, 2522ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson r.top + Math.abs(p.getFontMetrics().ascent) + EVENT_TEXT_TOP_MARGIN , p); 2523ba25b7c5031eff91d0bd21d0eb9b581db4f52b33Isaac Katzenelson } 2524ba902466b19b11d587468e354edc58e542707747Michael Chan } 252595f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan } 2526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 252795f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan private void drawHours(Rect r, Canvas canvas, Paint p) { 25288f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan setupHourTextPaint(p); 2529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 25308f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan int y = HOUR_GAP + mHoursTextHeight + HOURS_TOP_MARGIN; 2531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < 24; i++) { 2533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String time = mHourStrs[i]; 25348f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan canvas.drawText(time, HOURS_LEFT_MARGIN, y, p); 2535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += mCellHeight + HOUR_GAP; 2536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 25398f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan private void setupHourTextPaint(Paint p) { 25408f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setColor(mCalendarHourLabelColor); 2541e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextSize(HOURS_TEXT_SIZE); 2542f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(Typeface.DEFAULT); 2543e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextAlign(Paint.Align.RIGHT); 25448f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan p.setAntiAlias(true); 25458f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan } 25468f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan 2547e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private void drawDayHeader(String dayStr, int day, int cell, Canvas canvas, Paint p) { 2548487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan int dateNum = mFirstVisibleDate + day; 2549e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int x; 2550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (dateNum > mMonthLength) { 2551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project dateNum -= mMonthLength; 2552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2553e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(true); 2554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2555763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik int todayIndex = mTodayJulianDay - mFirstJulianDay; 25563eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 25573eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan String dateNumStr = String.valueOf(dateNum); 25583eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan if (mNumDays > 1) { 25593eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan float y = DAY_HEADER_HEIGHT - DAY_HEADER_BOTTOM_MARGIN; 25603eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 25613eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 2562e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik x = computeDayLeftPosition(day + 1) - DAY_HEADER_RIGHT_MARGIN; 2563e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextAlign(Align.RIGHT); 25643eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 2565763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik 2566763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik p.setTypeface(todayIndex == day ? mBold : Typeface.DEFAULT); 25673eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dateNumStr, x, y, p); 25683eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 25693eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the week 2570e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik x -= p.measureText(" " + dateNumStr); 25713eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 2572f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(Typeface.DEFAULT); 25733eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dayStr, x, y, p); 2574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 2575e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik float y = ONE_DAY_HEADER_HEIGHT - DAY_HEADER_ONE_DAY_BOTTOM_MARGIN; 2576e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setTextAlign(Align.LEFT); 2577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2578f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan 25793eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the week 2580e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik x = computeDayLeftPosition(day) + DAY_HEADER_ONE_DAY_LEFT_MARGIN; 25813eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DAY_HEADER_FONT_SIZE); 2582f1495b68983082cb7d1cd625abefcd87dd58cf5fMichael Chan p.setTypeface(Typeface.DEFAULT); 25833eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dayStr, x, y, p); 2584d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan 25853eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw day of the month 25863eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan x += p.measureText(dayStr) + DAY_HEADER_ONE_DAY_RIGHT_MARGIN; 25873eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setTextSize(DATE_HEADER_FONT_SIZE); 2588763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik p.setTypeface(todayIndex == day ? mBold : Typeface.DEFAULT); 25893eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan canvas.drawText(dateNumStr, x, y, p); 2590d06a1bf1cf81b818b3e3dc0f81b7cb07382425f2Michael Chan } 2591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void drawGridBackground(Rect r, Canvas canvas, Paint p) { 2594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint.Style savedStyle = p.getStyle(); 2595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2596b03348cec4c175846f074a656db5c121d5467e2dMichael Chan final float stopX = computeDayLeftPosition(mNumDays); 2597000ba1109e2f4e527e9227fe341598ceeb3fbca6Michael Chan float y = 0; 25983eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float deltaY = mCellHeight + HOUR_GAP; 259902041687c35441e8a21cb763f1fc3a26525292efDavid Brown int linesIndex = 0; 26003eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startY = 0; 26013eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float stopY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP); 26021ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan float x = mHoursWidth; 2603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 26043eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner horizontal grid lines 26053eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerHorizontalColor); 26063eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 2607e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 26083eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan y = 0; 260902041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 26103eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan for (int hour = 0; hour <= 24; hour++) { 26118f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mLines[linesIndex++] = GRID_LINE_LEFT_MARGIN; 261202041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 261302041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopX; 261402041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = y; 26153eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan y += deltaY; 26163eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 261702041687c35441e8a21cb763f1fc3a26525292efDavid Brown if (mCalendarGridLineInnerVerticalColor != mCalendarGridLineInnerHorizontalColor) { 261802041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 261902041687c35441e8a21cb763f1fc3a26525292efDavid Brown linesIndex = 0; 262002041687c35441e8a21cb763f1fc3a26525292efDavid Brown p.setColor(mCalendarGridLineInnerVerticalColor); 262102041687c35441e8a21cb763f1fc3a26525292efDavid Brown } 26223eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 26233eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner vertical grid lines 2624e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik for (int day = 0; day <= mNumDays; day++) { 2625e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik x = computeDayLeftPosition(day); 262602041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 262702041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 262802041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 262902041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 26303eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 263102041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 26323eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 2633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Restore the saved style. 2634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setStyle(savedStyle); 2635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setAntiAlias(true); 2636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2638e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik /** 2639e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * @param r 2640e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * @param canvas 2641e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * @param p 2642e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik */ 2643e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private void drawBgColors(Rect r, Canvas canvas, Paint p) { 2644e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int todayIndex = mTodayJulianDay - mFirstJulianDay; 2645e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik // Draw the hours background color 2646e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.top = mDestRect.top; 2647e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.bottom = mDestRect.bottom; 2648e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.left = 0; 2649e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.right = mHoursWidth; 2650e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setColor(mBgColor); 2651e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setStyle(Style.FILL); 2652e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 2653e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik canvas.drawRect(r, p); 265421bd42039c92232647f54461cd20708224cc7eb6Michael Chan 265521bd42039c92232647f54461cd20708224cc7eb6Michael Chan // Draw background for grid area 2656e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik if (mNumDays == 1 && todayIndex == 0) { 2657e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik // Draw a white background for the time later than current time 2658e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int lineY = mCurrentTime.hour * (mCellHeight + HOUR_GAP) 2659e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik + ((mCurrentTime.minute * mCellHeight) / 60) + 1; 2660e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik if (lineY < mViewStartY + mViewHeight) { 2661e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik lineY = Math.max(lineY, mViewStartY); 2662e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.left = mHoursWidth; 2663e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.right = mViewWidth; 2664e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.top = lineY; 2665e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.bottom = mViewStartY + mViewHeight; 266621bd42039c92232647f54461cd20708224cc7eb6Michael Chan p.setColor(mFutureBgColor); 2667e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik canvas.drawRect(r, p); 2668e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2669e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } else if (todayIndex >= 0 && todayIndex < mNumDays) { 267021bd42039c92232647f54461cd20708224cc7eb6Michael Chan // Draw today with a white background for the time later than current time 267121bd42039c92232647f54461cd20708224cc7eb6Michael Chan int lineY = mCurrentTime.hour * (mCellHeight + HOUR_GAP) 267221bd42039c92232647f54461cd20708224cc7eb6Michael Chan + ((mCurrentTime.minute * mCellHeight) / 60) + 1; 267321bd42039c92232647f54461cd20708224cc7eb6Michael Chan if (lineY < mViewStartY + mViewHeight) { 267421bd42039c92232647f54461cd20708224cc7eb6Michael Chan lineY = Math.max(lineY, mViewStartY); 267521bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.left = computeDayLeftPosition(todayIndex) + 1; 267621bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.right = computeDayLeftPosition(todayIndex + 1); 267721bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.top = lineY; 267821bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.bottom = mViewStartY + mViewHeight; 267921bd42039c92232647f54461cd20708224cc7eb6Michael Chan p.setColor(mFutureBgColor); 268021bd42039c92232647f54461cd20708224cc7eb6Michael Chan canvas.drawRect(r, p); 268121bd42039c92232647f54461cd20708224cc7eb6Michael Chan } 268221bd42039c92232647f54461cd20708224cc7eb6Michael Chan 268321bd42039c92232647f54461cd20708224cc7eb6Michael Chan // Paint Tomorrow and later days with future color 268421bd42039c92232647f54461cd20708224cc7eb6Michael Chan if (todayIndex + 1 < mNumDays) { 268521bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.left = computeDayLeftPosition(todayIndex + 1) + 1; 2686b03348cec4c175846f074a656db5c121d5467e2dMichael Chan r.right = computeDayLeftPosition(mNumDays); 268721bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.top = mDestRect.top; 268821bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.bottom = mDestRect.bottom; 268921bd42039c92232647f54461cd20708224cc7eb6Michael Chan p.setColor(mFutureBgColor); 269021bd42039c92232647f54461cd20708224cc7eb6Michael Chan canvas.drawRect(r, p); 269121bd42039c92232647f54461cd20708224cc7eb6Michael Chan } 269221bd42039c92232647f54461cd20708224cc7eb6Michael Chan } else if (todayIndex < 0) { 269321bd42039c92232647f54461cd20708224cc7eb6Michael Chan // Future 269421bd42039c92232647f54461cd20708224cc7eb6Michael Chan r.left = computeDayLeftPosition(0) + 1; 2695b03348cec4c175846f074a656db5c121d5467e2dMichael Chan r.right = computeDayLeftPosition(mNumDays); 2696e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.top = mDestRect.top; 2697e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik r.bottom = mDestRect.bottom; 269821bd42039c92232647f54461cd20708224cc7eb6Michael Chan p.setColor(mFutureBgColor); 2699e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik canvas.drawRect(r, p); 2700e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2701e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(true); 2702e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2703e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 2704146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event getSelectedEvent() { 2705146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null) { 2706146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // There is no event at the selected hour, so create a new event. 2707146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return getNewEvent(mSelectionDay, getSelectedTimeInMillis(), 2708146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getSelectedMinutesSinceMidnight()); 2709146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2710146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return mSelectedEvent; 2711146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2712146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2713146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean isEventSelected() { 2714146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return (mSelectedEvent != null); 2715146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2716146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2717146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event getNewEvent() { 2718146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return getNewEvent(mSelectionDay, getSelectedTimeInMillis(), 2719146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project getSelectedMinutesSinceMidnight()); 2720146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2721146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2722146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project static Event getNewEvent(int julianDay, long utcMillis, 2723146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int minutesSinceMidnight) { 2724146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = Event.newInstance(); 2725146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startDay = julianDay; 2726146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endDay = julianDay; 2727146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startMillis = utcMillis; 2728146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endMillis = event.startMillis + MILLIS_PER_HOUR; 2729146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.startTime = minutesSinceMidnight; 2730146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.endTime = event.startTime + MINUTES_PER_HOUR; 2731146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return event; 2732146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2733146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2734146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private int computeMaxStringWidth(int currentMax, String[] strings, Paint p) { 2735146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float maxWidthF = 0.0f; 2736146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2737146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = strings.length; 2738146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < len; i++) { 2739146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float width = p.measureText(strings[i]); 2740146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxWidthF = Math.max(width, maxWidthF); 2741146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2742146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxWidth = (int) (maxWidthF + 0.5); 2743146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (maxWidth < currentMax) { 2744146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxWidth = currentMax; 2745146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2746146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return maxWidth; 2747146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2748146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2749146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void saveSelectionPosition(float left, float top, float right, float bottom) { 2750146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.left = (int) left; 2751146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.right = (int) right; 2752146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.top = (int) top; 2753146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevBox.bottom = (int) bottom; 2754146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2755146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2756146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private Rect getCurrentSelectionPosition() { 2757146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect box = new Rect(); 2758146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.top = mSelectionHour * (mCellHeight + HOUR_GAP); 2759146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project box.bottom = box.top + mCellHeight + HOUR_GAP; 2760146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int daynum = mSelectionDay - mFirstJulianDay; 2761e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik box.left = computeDayLeftPosition(daynum) + 1; 2762e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik box.right = computeDayLeftPosition(daynum + 1); 2763146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return box; 2764146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2765146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 27661ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void setupTextRect(Rect r) { 27671ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom <= r.top || r.right <= r.left) { 27681ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top; 27691ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = r.left; 277036a4668f603c432d08ad156cd7c731f9838c0212Michael Chan return; 277136a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 277236a4668f603c432d08ad156cd7c731f9838c0212Michael Chan 27731ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom - r.top > EVENT_TEXT_TOP_MARGIN + EVENT_TEXT_BOTTOM_MARGIN) { 27741ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top += EVENT_TEXT_TOP_MARGIN; 27751ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom -= EVENT_TEXT_BOTTOM_MARGIN; 277636a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 27771ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.right - r.left > EVENT_TEXT_LEFT_MARGIN + EVENT_TEXT_RIGHT_MARGIN) { 27781ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left += EVENT_TEXT_LEFT_MARGIN; 27791ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right -= EVENT_TEXT_RIGHT_MARGIN; 278036a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 27819c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan } 27829c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan 27831ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void setupAllDayTextRect(Rect r) { 27841ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom <= r.top || r.right <= r.left) { 27851ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = r.top; 27861ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = r.left; 278736a4668f603c432d08ad156cd7c731f9838c0212Michael Chan return; 278836a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 278936a4668f603c432d08ad156cd7c731f9838c0212Michael Chan 27901ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.bottom - r.top > EVENT_ALL_DAY_TEXT_TOP_MARGIN + EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN) { 27911ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top += EVENT_ALL_DAY_TEXT_TOP_MARGIN; 27921ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom -= EVENT_ALL_DAY_TEXT_BOTTOM_MARGIN; 279336a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 27941ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (r.right - r.left > EVENT_ALL_DAY_TEXT_LEFT_MARGIN + EVENT_ALL_DAY_TEXT_RIGHT_MARGIN) { 27951ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left += EVENT_ALL_DAY_TEXT_LEFT_MARGIN; 27961ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right -= EVENT_ALL_DAY_TEXT_RIGHT_MARGIN; 279736a4668f603c432d08ad156cd7c731f9838c0212Michael Chan } 27989c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan } 27999c1f7b6c194a42a39bacdaa25e887dc5f12ec478Michael Chan 28003e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh /** 28013e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh * Return the layout for a numbered event. Create it if not already existing 28023e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh */ 280308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private StaticLayout getEventLayout(StaticLayout[] layouts, int i, Event event, Paint paint, 280408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan Rect r) { 280508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (i < 0 || i >= layouts.length) { 28060a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan return null; 28070a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan } 28080a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan 280908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = layouts[i]; 2810f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan // Check if we have already initialized the StaticLayout and that 2811f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan // the width hasn't changed (due to vertical resizing which causes 2812f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan // re-layout of events at min height) 28131ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (layout == null || r.width() != layout.getWidth()) { 2814e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik SpannableStringBuilder bob = new SpannableStringBuilder(); 2815e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik if (event.title != null) { 28161c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik // MAX - 1 since we add a space 28171c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik bob.append(drawTextSanitizer(event.title.toString(), MAX_EVENT_TEXT_LEN - 1)); 2818e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik bob.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, bob.length(), 0); 2819e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik bob.append(' '); 2820e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 2821e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik if (event.location != null) { 2822e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik bob.append(drawTextSanitizer(event.location.toString(), 2823e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik MAX_EVENT_TEXT_LEN - bob.length())); 2824e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik } 28253e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 282625996100d6ea61888ebe54d7708a9a371bb12a55RoboErik switch (event.selfAttendeeStatus) { 282725996100d6ea61888ebe54d7708a9a371bb12a55RoboErik case Attendees.ATTENDEE_STATUS_INVITED: 282825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik paint.setColor(event.color); 282925996100d6ea61888ebe54d7708a9a371bb12a55RoboErik break; 283025996100d6ea61888ebe54d7708a9a371bb12a55RoboErik case Attendees.ATTENDEE_STATUS_DECLINED: 2831e6109c584d27a6c25df1819a5c6ec444e789ce61Isaac Katzenelson paint.setColor(mEventTextColor); 28324ecf0648e68bc9339a3d64745008a4617f7beddaIsaac Katzenelson paint.setAlpha(Utils.DECLINED_EVENT_TEXT_ALPHA); 2833e6109c584d27a6c25df1819a5c6ec444e789ce61Isaac Katzenelson break; 283425996100d6ea61888ebe54d7708a9a371bb12a55RoboErik case Attendees.ATTENDEE_STATUS_NONE: // Your own events 283525996100d6ea61888ebe54d7708a9a371bb12a55RoboErik case Attendees.ATTENDEE_STATUS_ACCEPTED: 283625996100d6ea61888ebe54d7708a9a371bb12a55RoboErik case Attendees.ATTENDEE_STATUS_TENTATIVE: 283725996100d6ea61888ebe54d7708a9a371bb12a55RoboErik default: 283825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik paint.setColor(mEventTextColor); 283925996100d6ea61888ebe54d7708a9a371bb12a55RoboErik break; 2840f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan } 2841f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan 28423e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh // Leave a one pixel boundary on the left and right of the rectangle for the event 2843e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik layout = new StaticLayout(bob, 0, bob.length(), new TextPaint(paint), r.width(), 28441ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true, null, r.width()); 28453e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 284608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan layouts[i] = layout; 28473e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 28480a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson layout.getPaint().setAlpha(mEventsAlpha); 28493e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh return layout; 28503e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh } 28513e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 28521ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan private void drawAllDayEvents(int firstDay, int numDays, Canvas canvas, Paint p) { 28533e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh 2854146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextSize(NORMAL_FONT_SIZE); 2855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setTextAlign(Paint.Align.LEFT); 2856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint eventTextPaint = mEventTextPaint; 2857146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 28583eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan final float startY = DAY_HEADER_HEIGHT; 28592fda24534978f55711526dbde747aa50d68dec40RoboErik final float stopY = startY + mAlldayHeight + ALLDAY_TOP_MARGIN; 2860e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik float x = 0; 286102041687c35441e8a21cb763f1fc3a26525292efDavid Brown int linesIndex = 0; 28623eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan 28633eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Draw the inner vertical grid lines 28643eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setColor(mCalendarGridLineInnerVerticalColor); 28651ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan x = mHoursWidth; 28663eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan p.setStrokeWidth(GRID_LINE_INNER_WIDTH); 28671ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // Line bounding the top of the all day area 28688f7a2b2fb82029bc23fce357d14f4484e80c13fdMichael Chan mLines[linesIndex++] = GRID_LINE_LEFT_MARGIN; 28691ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 2870b03348cec4c175846f074a656db5c121d5467e2dMichael Chan mLines[linesIndex++] = computeDayLeftPosition(mNumDays); 28711ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan mLines[linesIndex++] = startY; 28721ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 2873e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik for (int day = 0; day <= mNumDays; day++) { 2874e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik x = computeDayLeftPosition(day); 287502041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 287602041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = startY; 287702041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = x; 287802041687c35441e8a21cb763f1fc3a26525292efDavid Brown mLines[linesIndex++] = stopY; 28793eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan } 2880e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 288102041687c35441e8a21cb763f1fc3a26525292efDavid Brown canvas.drawLines(mLines, 0, linesIndex, p); 2882146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project p.setStyle(Style.FILL); 2883146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 28843eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int y = DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 2885146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int lastDay = firstDay + numDays - 1; 288608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final ArrayList<Event> events = mAllDayEvents; 2887146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 28882fda24534978f55711526dbde747aa50d68dec40RoboErik // Whether or not we should draw the more events text 28892fda24534978f55711526dbde747aa50d68dec40RoboErik boolean hasMoreEvents = false; 28902fda24534978f55711526dbde747aa50d68dec40RoboErik // size of the allDay area 28912fda24534978f55711526dbde747aa50d68dec40RoboErik float drawHeight = mAlldayHeight; 28922fda24534978f55711526dbde747aa50d68dec40RoboErik // max number of events being drawn in one day of the allday area 28932fda24534978f55711526dbde747aa50d68dec40RoboErik float numRectangles = mMaxAlldayEvents; 28942fda24534978f55711526dbde747aa50d68dec40RoboErik // Where to cut off drawn allday events 28952fda24534978f55711526dbde747aa50d68dec40RoboErik int allDayEventClip = DAY_HEADER_HEIGHT + mAlldayHeight + ALLDAY_TOP_MARGIN; 28962fda24534978f55711526dbde747aa50d68dec40RoboErik // The number of events that weren't drawn in each day 28972fda24534978f55711526dbde747aa50d68dec40RoboErik mSkippedAlldayEvents = new int[numDays]; 28982fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount && !mShowAllAllDayEvents && 28992fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayHeight == 0) { 29002fda24534978f55711526dbde747aa50d68dec40RoboErik // We draw one fewer event than will fit so that more events text 29012fda24534978f55711526dbde747aa50d68dec40RoboErik // can be drawn 29022fda24534978f55711526dbde747aa50d68dec40RoboErik numRectangles = mMaxUnexpandedAlldayEventCount - 1; 29032fda24534978f55711526dbde747aa50d68dec40RoboErik // We also clip the events above the more events text 29042fda24534978f55711526dbde747aa50d68dec40RoboErik allDayEventClip -= MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT; 29052fda24534978f55711526dbde747aa50d68dec40RoboErik hasMoreEvents = true; 29062fda24534978f55711526dbde747aa50d68dec40RoboErik } else if (mAnimateDayHeight != 0) { 29072fda24534978f55711526dbde747aa50d68dec40RoboErik // clip at the end of the animating space 29082fda24534978f55711526dbde747aa50d68dec40RoboErik allDayEventClip = DAY_HEADER_HEIGHT + mAnimateDayHeight + ALLDAY_TOP_MARGIN; 29092fda24534978f55711526dbde747aa50d68dec40RoboErik } 29100a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson 29110a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson int alpha = eventTextPaint.getAlpha(); 29120a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson eventTextPaint.setAlpha(mEventsAlpha); 2913146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 2914146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 2915146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startDay = event.startDay; 2916146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endDay = event.endDay; 2917c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (startDay > lastDay || endDay < firstDay) { 2918146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 2919c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2920c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (startDay < firstDay) { 2921146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startDay = firstDay; 2922c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2923c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa if (endDay > lastDay) { 2924146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endDay = lastDay; 2925c514df21767542285fe6cf333b148fff079a30f2Daisuke Miyakawa } 2926146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startIndex = startDay - firstDay; 2927146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endIndex = endDay - firstDay; 29282fda24534978f55711526dbde747aa50d68dec40RoboErik float height = mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount ? mAnimateDayEventHeight : 29292fda24534978f55711526dbde747aa50d68dec40RoboErik drawHeight / numRectangles; 2930146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2931146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Prevent a single event from getting too big 2932f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan if (height > MAX_HEIGHT_OF_ONE_ALLDAY_EVENT) { 2933f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan height = MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 2934146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2935146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2936146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Leave a one-pixel space between the vertical day lines and the 2937146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event rectangle. 2938e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik event.left = computeDayLeftPosition(startIndex); 2939e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik event.right = computeDayLeftPosition(endIndex + 1) - DAY_GAP; 2940146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project event.top = y + height * event.getColumn(); 294125996100d6ea61888ebe54d7708a9a371bb12a55RoboErik event.bottom = event.top + height - ALL_DAY_EVENT_RECT_BOTTOM_MARGIN; 29422fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount) { 29432fda24534978f55711526dbde747aa50d68dec40RoboErik // check if we should skip this event. We skip if it starts 29442fda24534978f55711526dbde747aa50d68dec40RoboErik // after the clip bound or ends after the skip bound and we're 29452fda24534978f55711526dbde747aa50d68dec40RoboErik // not animating. 29462fda24534978f55711526dbde747aa50d68dec40RoboErik if (event.top >= allDayEventClip) { 29472fda24534978f55711526dbde747aa50d68dec40RoboErik incrementSkipCount(mSkippedAlldayEvents, startIndex, endIndex); 29482fda24534978f55711526dbde747aa50d68dec40RoboErik continue; 29492fda24534978f55711526dbde747aa50d68dec40RoboErik } else if (event.bottom > allDayEventClip) { 29502fda24534978f55711526dbde747aa50d68dec40RoboErik if (hasMoreEvents) { 29512fda24534978f55711526dbde747aa50d68dec40RoboErik incrementSkipCount(mSkippedAlldayEvents, startIndex, endIndex); 29522fda24534978f55711526dbde747aa50d68dec40RoboErik continue; 29532fda24534978f55711526dbde747aa50d68dec40RoboErik } 29542fda24534978f55711526dbde747aa50d68dec40RoboErik event.bottom = allDayEventClip; 29552fda24534978f55711526dbde747aa50d68dec40RoboErik } 29562fda24534978f55711526dbde747aa50d68dec40RoboErik } 295725996100d6ea61888ebe54d7708a9a371bb12a55RoboErik Rect r = drawEventRect(event, canvas, p, eventTextPaint, (int) event.top, 295825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik (int) event.bottom); 29591ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan setupAllDayTextRect(r); 296008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = getEventLayout(mAllDayLayouts, i, event, eventTextPaint, r); 29616ab3a2c7de3719a4806d6c9cd5b53cb34a5bb017Mindy Pereira drawEventText(layout, r, canvas, r.top, r.bottom, true); 2962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check if this all-day event intersects the selected day 29642fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSelectionAllday && mComputeSelectedEvents) { 2965146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (startDay <= mSelectionDay && endDay >= mSelectionDay) { 2966146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 2967146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2968146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2969146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 29700a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson eventTextPaint.setAlpha(alpha); 29710a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson 29722fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMoreAlldayEventsTextAlpha != 0 && mSkippedAlldayEvents != null) { 29732fda24534978f55711526dbde747aa50d68dec40RoboErik // If the more allday text should be visible, draw it. 29740a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson alpha = p.getAlpha(); 29750a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson p.setAlpha(mEventsAlpha); 29762fda24534978f55711526dbde747aa50d68dec40RoboErik p.setColor(mMoreAlldayEventsTextAlpha << 24 & mMoreEventsTextColor); 29772fda24534978f55711526dbde747aa50d68dec40RoboErik for (int i = 0; i < mSkippedAlldayEvents.length; i++) { 29782fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSkippedAlldayEvents[i] > 0) { 29792fda24534978f55711526dbde747aa50d68dec40RoboErik drawMoreAlldayEvents(canvas, mSkippedAlldayEvents[i], i, p); 29802fda24534978f55711526dbde747aa50d68dec40RoboErik } 29812fda24534978f55711526dbde747aa50d68dec40RoboErik } 29820a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson p.setAlpha(alpha); 29832fda24534978f55711526dbde747aa50d68dec40RoboErik } 2984146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 29852fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSelectionAllday) { 2986146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the neighbors for the list of all-day events that 2987146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // intersect the selected day. 2988146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeAllDayNeighbors(); 2989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 2990146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Set the selection position to zero so that when we move down 2991146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // to the normal event area, we will highlight the topmost event. 2992146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project saveSelectionPosition(0f, 0f, 0f, 0f); 2993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 2995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 29962fda24534978f55711526dbde747aa50d68dec40RoboErik // Helper method for counting the number of allday events skipped on each day 29972fda24534978f55711526dbde747aa50d68dec40RoboErik private void incrementSkipCount(int[] counts, int startIndex, int endIndex) { 29982fda24534978f55711526dbde747aa50d68dec40RoboErik if (counts == null || startIndex < 0 || endIndex > counts.length) { 29992fda24534978f55711526dbde747aa50d68dec40RoboErik return; 30002fda24534978f55711526dbde747aa50d68dec40RoboErik } 30012fda24534978f55711526dbde747aa50d68dec40RoboErik for (int i = startIndex; i <= endIndex; i++) { 30022fda24534978f55711526dbde747aa50d68dec40RoboErik counts[i]++; 30032fda24534978f55711526dbde747aa50d68dec40RoboErik } 30042fda24534978f55711526dbde747aa50d68dec40RoboErik } 30052fda24534978f55711526dbde747aa50d68dec40RoboErik 30062fda24534978f55711526dbde747aa50d68dec40RoboErik // Draws the "box +n" text for hidden allday events 30072fda24534978f55711526dbde747aa50d68dec40RoboErik protected void drawMoreAlldayEvents(Canvas canvas, int remainingEvents, int day, Paint p) { 3008e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int x = computeDayLeftPosition(day) + EVENT_ALL_DAY_TEXT_LEFT_MARGIN; 3009e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int y = (int) (mAlldayHeight - .5f * MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT - .5f 3010e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik * EVENT_SQUARE_WIDTH + DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN); 3011763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik Rect r = mRect; 3012763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.top = y; 3013763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.left = x; 3014763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.bottom = y + EVENT_SQUARE_WIDTH; 3015763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik r.right = x + EVENT_SQUARE_WIDTH; 3016e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setColor(mMoreEventsTextColor); 3017e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setStrokeWidth(EVENT_RECT_STROKE_WIDTH); 3018763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik p.setStyle(Style.STROKE); 3019e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 3020763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik canvas.drawRect(r, p); 3021e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(true); 3022763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik p.setStyle(Style.FILL); 3023763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik p.setTextSize(EVENT_TEXT_FONT_SIZE); 30242fda24534978f55711526dbde747aa50d68dec40RoboErik String text = mResources.getQuantityString(R.plurals.month_more_events, remainingEvents); 30252fda24534978f55711526dbde747aa50d68dec40RoboErik y += EVENT_SQUARE_WIDTH; 30262fda24534978f55711526dbde747aa50d68dec40RoboErik x += EVENT_SQUARE_WIDTH + EVENT_LINE_PADDING; 30272fda24534978f55711526dbde747aa50d68dec40RoboErik canvas.drawText(String.format(text, remainingEvents), x, y, p); 30282fda24534978f55711526dbde747aa50d68dec40RoboErik } 30292fda24534978f55711526dbde747aa50d68dec40RoboErik 3030146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeAllDayNeighbors() { 3031146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 3032146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len == 0 || mSelectedEvent != null) { 3033146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3034146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3035146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3036146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear all the links 3037146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 3038146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 3039146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = null; 3040146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = null; 3041146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = null; 3042146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = null; 3043146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3044146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3045146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each event in the selected event list "mSelectedEvents", find 304646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // its neighbors in the up and down directions. This could be done 3047146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // more efficiently by sorting on the Event.getColumn() field, but 3048146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the list is expected to be very small. 3049146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3050146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Find the event in the same row as the previously selected all-day 3051146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // event, if any. 3052146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startPosition = -1; 305368655b5af2b7e5f872a103858ec58a19042123ceRoboErik if (mPrevSelectedEvent != null && mPrevSelectedEvent.drawAsAllday()) { 3054146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startPosition = mPrevSelectedEvent.getColumn(); 3055146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3056146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int maxPosition = -1; 3057146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event startEvent = null; 3058146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event maxPositionEvent = null; 3059146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 3060146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 3061146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int position = ev.getColumn(); 3062146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (position == startPosition) { 3063146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEvent = ev; 3064146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (position > maxPosition) { 3065146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxPositionEvent = ev; 3066146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project maxPosition = position; 3067146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3068146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int jj = 0; jj < len; jj++) { 3069146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (jj == ii) { 3070146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3071146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3072146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event neighbor = mSelectedEvents.get(jj); 3073146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborPosition = neighbor.getColumn(); 3074146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborPosition == position - 1) { 3075146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = neighbor; 3076146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborPosition == position + 1) { 3077146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = neighbor; 3078146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3079146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3080146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3081146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (startEvent != null) { 3082989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(startEvent); 3083146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3084989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(maxPositionEvent); 3085146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3086146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3087146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3088e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik private void drawEvents(int date, int dayIndex, int top, Canvas canvas, Paint p) { 3089146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Paint eventTextPaint = mEventTextPaint; 3090763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik int left = computeDayLeftPosition(dayIndex) + 1; 3091763b9308fa13c8c9c3b9a715f4daf8eba497b935RoboErik int cellWidth = computeDayLeftPosition(dayIndex + 1) - left + 1; 3092146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellHeight = mCellHeight; 3093146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3094146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use the selected hour as the selection region 3095259b8f9a21fffd3858218581e9daaf689b6b888fErik Rect selectionArea = mSelectionRect; 3096146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.top = top + mSelectionHour * (cellHeight + HOUR_GAP); 3097146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.bottom = selectionArea.top + cellHeight; 3098146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.left = left; 3099146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project selectionArea.right = selectionArea.left + cellWidth; 3100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 310108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan final ArrayList<Event> events = mEvents; 3102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 3103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project EventGeometry geometry = mEventGeometry; 3104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 31052fda24534978f55711526dbde747aa50d68dec40RoboErik final int viewEndY = mViewStartY + mViewHeight - DAY_HEADER_HEIGHT - mAlldayHeight; 31060a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson 31070a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson int alpha = eventTextPaint.getAlpha(); 31080a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson eventTextPaint.setAlpha(mEventsAlpha); 3109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 3110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 3111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!geometry.computeEventRect(date, left, top, cellWidth, event)) { 3112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 311508ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Don't draw it if it is not visible 311608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (event.bottom < mViewStartY || event.top > viewEndY) { 311708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan continue; 311808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 311908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 31202fda24534978f55711526dbde747aa50d68dec40RoboErik if (date == mSelectionDay && !mSelectionAllday && mComputeSelectedEvents 3121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && geometry.eventIntersectsSelection(event, selectionArea)) { 3122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 3123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 312525996100d6ea61888ebe54d7708a9a371bb12a55RoboErik Rect r = drawEventRect(event, canvas, p, eventTextPaint, mViewStartY, viewEndY); 31261ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan setupTextRect(r); 312708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 312808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // Don't draw text if it is not visible 312908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (r.top > viewEndY || r.bottom < mViewStartY) { 313008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan continue; 313108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } 313208ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan StaticLayout layout = getEventLayout(mLayouts, i, event, eventTextPaint, r); 313308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // TODO: not sure why we are 4 pixels off 313446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan drawEventText(layout, r, canvas, mViewStartY + 4, mViewStartY + mViewHeight 31356ab3a2c7de3719a4806d6c9cd5b53cb34a5bb017Mindy Pereira - DAY_HEADER_HEIGHT - mAlldayHeight, false); 3136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 31370a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson eventTextPaint.setAlpha(alpha); 3138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 31392fda24534978f55711526dbde747aa50d68dec40RoboErik if (date == mSelectionDay && !mSelectionAllday && isFocused() 3140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project && mSelectionMode != SELECTION_HIDDEN) { 3141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeNeighbors(); 3142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Computes the "nearest" neighbor event in four directions (left, right, 3146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // up, down) for each of the events in the mSelectedEvents array. 3147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void computeNeighbors() { 3148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 3149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (len == 0 || mSelectedEvent != null) { 3150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // First, clear all the links 3154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 3155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 3156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = null; 3157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = null; 3158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = null; 3159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = null; 3160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event startEvent = mSelectedEvents.get(0); 316346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int startEventDistance1 = 100000; // any large number 316446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int startEventDistance2 = 100000; // any large number 3165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevLocation = FROM_NONE; 3166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevTop; 3167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevBottom; 3168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevLeft; 3169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevRight; 3170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int prevCenter = 0; 3171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect box = getCurrentSelectionPosition(); 3172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPrevSelectedEvent != null) { 3173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = (int) mPrevSelectedEvent.top; 3174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = (int) mPrevSelectedEvent.bottom; 3175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = (int) mPrevSelectedEvent.left; 3176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = (int) mPrevSelectedEvent.right; 3177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Check if the previously selected event intersects the previous 317846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // selection box. (The previously selected event may be from a 3179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // much older selection box.) 3180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevTop >= mPrevBox.bottom || prevBottom <= mPrevBox.top 3181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || prevRight <= mPrevBox.left || prevLeft >= mPrevBox.right) { 3182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = null; 3183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 3184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 3185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = mPrevBox.left; 3186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = mPrevBox.right; 3187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Clip the top and bottom to the previous selection box. 3189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevTop < mPrevBox.top) { 3190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 3191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevBottom > mPrevBox.bottom) { 3193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 3194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Just use the previously drawn selection box 3198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevTop = mPrevBox.top; 3199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevBottom = mPrevBox.bottom; 3200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLeft = mPrevBox.left; 3201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevRight = mPrevBox.right; 3202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Figure out where we came from and compute the center of that area. 3205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevLeft >= box.right) { 3206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was to the right of us. 3207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_RIGHT; 3208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevTop + prevBottom) / 2; 3209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevRight <= box.left) { 3210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was to the left of us. 3211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_LEFT; 3212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevTop + prevBottom) / 2; 3213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevBottom <= box.top) { 3214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was above us. 3215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_ABOVE; 3216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevLeft + prevRight) / 2; 3217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevTop >= box.bottom) { 3218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The previously selected event was below us. 3219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevLocation = FROM_BELOW; 3220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project prevCenter = (prevLeft + prevRight) / 2; 3221146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each event in the selected event list "mSelectedEvents", search 3224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // all the other events in that list for the nearest neighbor in 4 3225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // directions. 3226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int ii = 0; ii < len; ii++) { 3227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(ii); 3228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startTime = ev.startTime; 3230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endTime = ev.endTime; 3231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int left = (int) ev.left; 3232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int right = (int) ev.right; 3233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int top = (int) ev.top; 3234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (top < box.top) { 3235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project top = box.top; 3236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int bottom = (int) ev.bottom; 3238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom > box.bottom) { 3239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project bottom = box.bottom; 3240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 324121bd42039c92232647f54461cd20708224cc7eb6Michael Chan// if (false) { 324221bd42039c92232647f54461cd20708224cc7eb6Michael Chan// int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL 324321bd42039c92232647f54461cd20708224cc7eb6Michael Chan// | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 324421bd42039c92232647f54461cd20708224cc7eb6Michael Chan// if (DateFormat.is24HourFormat(mContext)) { 324521bd42039c92232647f54461cd20708224cc7eb6Michael Chan// flags |= DateUtils.FORMAT_24HOUR; 324621bd42039c92232647f54461cd20708224cc7eb6Michael Chan// } 324721bd42039c92232647f54461cd20708224cc7eb6Michael Chan// String timeRange = DateUtils.formatDateRange(mContext, ev.startMillis, 324821bd42039c92232647f54461cd20708224cc7eb6Michael Chan// ev.endMillis, flags); 324921bd42039c92232647f54461cd20708224cc7eb6Michael Chan// Log.i("Cal", "left: " + left + " right: " + right + " top: " + top + " bottom: " 325021bd42039c92232647f54461cd20708224cc7eb6Michael Chan// + bottom + " ev: " + timeRange + " " + ev.title); 325121bd42039c92232647f54461cd20708224cc7eb6Michael Chan// } 325246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int upDistanceMin = 10000; // any large number 325346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int downDistanceMin = 10000; // any large number 325446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int leftDistanceMin = 10000; // any large number 325546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int rightDistanceMin = 10000; // any large number 3256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event upEvent = null; 3257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event downEvent = null; 3258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event leftEvent = null; 3259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event rightEvent = null; 3260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the starting event closest to the previously selected event, 326246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // if any. distance1 takes precedence over distance2. 3263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance1 = 0; 3264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance2 = 0; 3265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (prevLocation == FROM_ABOVE) { 3266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (left >= prevCenter) { 3267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = left - prevCenter; 3268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (right <= prevCenter) { 3269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - right; 3270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = top - prevBottom; 3272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_BELOW) { 3273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (left >= prevCenter) { 3274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = left - prevCenter; 3275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (right <= prevCenter) { 3276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - right; 3277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = prevTop - bottom; 3279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_LEFT) { 3280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom <= prevCenter) { 3281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - bottom; 3282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (top >= prevCenter) { 3283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = top - prevCenter; 3284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = left - prevRight; 3286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (prevLocation == FROM_RIGHT) { 3287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (bottom <= prevCenter) { 3288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = prevCenter - bottom; 3289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (top >= prevCenter) { 3290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance1 = top - prevCenter; 3291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance2 = prevLeft - right; 3293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance1 < startEventDistance1 3295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || (distance1 == startEventDistance1 && distance2 < startEventDistance2)) { 3296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEvent = ev; 3297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEventDistance1 = distance1; 3298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project startEventDistance2 = distance2; 3299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // For each neighbor, figure out if it is above or below or left 3302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // or right of me and compute the distance. 3303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int jj = 0; jj < len; jj++) { 3304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (jj == ii) { 3305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 3306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event neighbor = mSelectedEvents.get(jj); 3308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborLeft = (int) neighbor.left; 3309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborRight = (int) neighbor.right; 3310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighbor.endTime <= startTime) { 3311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely above me. 3312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we overlap the same column, then compute the distance. 3313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft < right && neighborRight > left) { 3314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = startTime - neighbor.endTime; 3315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < upDistanceMin) { 3316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upDistanceMin = distance; 3317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upEvent = neighbor; 3318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == upDistanceMin) { 3319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (left + right) / 2; 3320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = 0; 3321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentLeft = (int) upEvent.left; 3322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentRight = (int) upEvent.right; 3323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (currentRight <= center) { 3324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = center - currentRight; 3325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (currentLeft >= center) { 3326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = currentLeft - center; 3327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = 0; 3330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborRight <= center) { 3331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = center - neighborRight; 3332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborLeft >= center) { 3333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = neighborLeft - center; 3334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 3336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upDistanceMin = distance; 3337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project upEvent = neighbor; 3338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighbor.startTime >= endTime) { 3342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely below me. 3343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we overlap the same column, then compute the distance. 3344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft < right && neighborRight > left) { 3345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = neighbor.startTime - endTime; 3346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < downDistanceMin) { 3347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downDistanceMin = distance; 3348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downEvent = neighbor; 3349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == downDistanceMin) { 3350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (left + right) / 2; 3351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = 0; 3352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentLeft = (int) downEvent.left; 3353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentRight = (int) downEvent.right; 3354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (currentRight <= center) { 3355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = center - currentRight; 3356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (currentLeft >= center) { 3357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project currentDistance = currentLeft - center; 3358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = 0; 3361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborRight <= center) { 3362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = center - neighborRight; 3363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborLeft >= center) { 3364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project neighborDistance = neighborLeft - center; 3365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 3367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downDistanceMin = distance; 3368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project downEvent = neighbor; 3369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborLeft >= right) { 3375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely to the right of me. 3376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Take the closest neighbor in the y direction. 3377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (top + bottom) / 2; 3378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = 0; 3379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborBottom = (int) neighbor.bottom; 3380146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborTop = (int) neighbor.top; 3381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborBottom <= center) { 3382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = center - neighborBottom; 3383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborTop >= center) { 3384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = neighborTop - center; 3385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < rightDistanceMin) { 3387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightDistanceMin = distance; 3388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightEvent = neighbor; 3389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == rightDistanceMin) { 3390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the closest in the x direction 3391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = neighborLeft - right; 3392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = (int) rightEvent.left - right; 3393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 3394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightDistanceMin = distance; 3395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project rightEvent = neighbor; 3396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborRight <= left) { 3399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // This neighbor is entirely to the left of me. 3400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Take the closest neighbor in the y direction. 3401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int center = (top + bottom) / 2; 3402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int distance = 0; 3403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborBottom = (int) neighbor.bottom; 3404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborTop = (int) neighbor.top; 3405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborBottom <= center) { 3406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = center - neighborBottom; 3407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (neighborTop >= center) { 3408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project distance = neighborTop - center; 3409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distance < leftDistanceMin) { 3411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftDistanceMin = distance; 3412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftEvent = neighbor; 3413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (distance == leftDistanceMin) { 3414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Pick the closest in the x direction 3415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int neighborDistance = left - neighborRight; 3416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int currentDistance = left - (int) leftEvent.right; 3417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (neighborDistance < currentDistance) { 3418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftDistanceMin = distance; 3419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project leftEvent = neighbor; 3420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextUp = upEvent; 3425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextDown = downEvent; 3426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextLeft = leftEvent; 3427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ev.nextRight = rightEvent; 3428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3429989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(startEvent); 3430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 343225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik private Rect drawEventRect(Event event, Canvas canvas, Paint p, Paint eventTextPaint, 343325996100d6ea61888ebe54d7708a9a371bb12a55RoboErik int visibleTop, int visibleBot) { 343411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw the Event Rect 34351ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan Rect r = mRect; 343625996100d6ea61888ebe54d7708a9a371bb12a55RoboErik r.top = Math.max((int) event.top + EVENT_RECT_TOP_MARGIN, visibleTop); 343725996100d6ea61888ebe54d7708a9a371bb12a55RoboErik r.bottom = Math.min((int) event.bottom - EVENT_RECT_BOTTOM_MARGIN, visibleBot); 34381ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = (int) event.left + EVENT_RECT_LEFT_MARGIN; 343925996100d6ea61888ebe54d7708a9a371bb12a55RoboErik r.right = (int) event.right; 34401ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 3441056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson int color; 3442056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson if (event == mClickedEvent) { 3443056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson color = mClickedColor; 3444056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson } else { 3445056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson color = event.color; 3446056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson } 3447056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson 3448f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan switch (event.selfAttendeeStatus) { 3449f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_INVITED: 3450056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson if (event != mClickedEvent) { 3451056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson p.setStyle(Style.STROKE); 3452056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson } 345325996100d6ea61888ebe54d7708a9a371bb12a55RoboErik break; 3454f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_DECLINED: 3455056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson if (event != mClickedEvent) { 3456056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson color = Utils.getDeclinedColorFromColor(color); 3457056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson } 3458f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_NONE: // Your own events 3459f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_ACCEPTED: 3460f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan case Attendees.ATTENDEE_STATUS_TENTATIVE: 3461f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan default: 346225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik p.setStyle(Style.FILL_AND_STROKE); 3463f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan break; 3464f2ca00946a543a19467d5dbfa3427ecf221186d4Michael Chan } 3465e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 3466e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(false); 3467e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik 3468aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan int floorHalfStroke = (int) Math.floor(EVENT_RECT_STROKE_WIDTH / 2.0f); 3469aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan int ceilHalfStroke = (int) Math.ceil(EVENT_RECT_STROKE_WIDTH / 2.0f); 3470aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan r.top = Math.max((int) event.top + EVENT_RECT_TOP_MARGIN + floorHalfStroke, visibleTop); 3471aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan r.bottom = Math.min((int) event.bottom - EVENT_RECT_BOTTOM_MARGIN - ceilHalfStroke, 3472aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan visibleBot); 3473aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan r.left += floorHalfStroke; 3474aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan r.right -= ceilHalfStroke; 3475aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan p.setStrokeWidth(EVENT_RECT_STROKE_WIDTH); 3476aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan p.setColor(color); 34770a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson int alpha = p.getAlpha(); 34780a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson p.setAlpha(mEventsAlpha); 3479aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan canvas.drawRect(r, p); 34800a30ef1efee8fee2a2aecb202afb56f971f3e604Isaac Katzenelson p.setAlpha(alpha); 34811ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setStyle(Style.FILL); 3482e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 3483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If this event is selected, then use the selection color 3484056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson if (mSelectedEvent == event && mClickedEvent != null) { 34851ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan boolean paintIt = false; 3486aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan color = 0; 3487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode == SELECTION_PRESSED) { 3488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 3489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 349078f58c119af15ed85a727e16cddd793ced4c809dMichael Chan color = mPressedColor; 34911ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan paintIt = true; 3492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionMode == SELECTION_SELECTED) { 3493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Also, remember the last selected event that we drew 3494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPrevSelectedEvent = event; 349578f58c119af15ed85a727e16cddd793ced4c809dMichael Chan color = mPressedColor; 34961ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan paintIt = true; 34971ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan } 34981ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 34991ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan if (paintIt) { 35001ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan p.setColor(color); 35011ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.drawRect(r, p); 3502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3503e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik p.setAntiAlias(true); 3504146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3505146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 350611ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw cal color square border 350725996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.top = (int) event.top + CALENDAR_COLOR_SQUARE_V_OFFSET; 350825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.left = (int) event.left + CALENDAR_COLOR_SQUARE_H_OFFSET; 350925996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.bottom = r.top + CALENDAR_COLOR_SQUARE_SIZE + 1; 351025996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.right = r.left + CALENDAR_COLOR_SQUARE_SIZE + 1; 351125996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // p.setColor(0xFFFFFFFF); 351225996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // canvas.drawRect(r, p); 35138af2529989a9b10a0bb84736695c22fc02a17a4aThe Android Open Source Project 351411ca73595534d2b2c18ab8c31a735c9e683c9379Michael Chan // Draw cal color 351525996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.top++; 351625996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.left++; 351725996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.bottom--; 351825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // r.right--; 351925996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // p.setColor(event.color); 352025996100d6ea61888ebe54d7708a9a371bb12a55RoboErik // canvas.drawRect(r, p); 3521e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 35223eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan // Setup rect for drawEventText which follows 35231ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.top = (int) event.top + EVENT_RECT_TOP_MARGIN; 35241ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.bottom = (int) event.bottom - EVENT_RECT_BOTTOM_MARGIN; 35251ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.left = (int) event.left + EVENT_RECT_LEFT_MARGIN; 35261ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan r.right = (int) event.right - EVENT_RECT_RIGHT_MARGIN; 35271ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan return r; 3528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3530056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson private final Pattern drawTextSanitizerFilter = Pattern.compile("[\t\n],"); 35310d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 35320d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // Sanitize a string before passing it to drawText or else we get little 35330d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // squares. For newlines and tabs before a comma, delete the character. 35340d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan // Otherwise, just replace them with a space. 3535f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan private String drawTextSanitizer(String string, int maxEventTextLen) { 35360d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan Matcher m = drawTextSanitizerFilter.matcher(string); 3537f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan string = m.replaceAll(","); 3538f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan 3539f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan int len = string.length(); 35401c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik if (maxEventTextLen <= 0) { 35411c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik string = ""; 35421c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik len = 0; 35431c1987163f49158d6ea54f034c874ec3d7b5cde1RoboErik } else if (len > maxEventTextLen) { 3544f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan string = string.substring(0, maxEventTextLen); 3545f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan len = maxEventTextLen; 3546f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan } 3547f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan 3548f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan return string.replace('\n', ' '); 35490d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan } 35500d53e947fce63b2a629ea2c32a882eb505e527f7Michael Chan 355108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan private void drawEventText(StaticLayout eventLayout, Rect rect, Canvas canvas, int top, 35526ab3a2c7de3719a4806d6c9cd5b53cb34a5bb017Mindy Pereira int bottom, boolean center) { 35531ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // drawEmptyRect(canvas, rect, 0xFFFF00FF); // for debugging 35541ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 35551ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int width = rect.right - rect.left; 35561ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan int height = rect.bottom - rect.top; 3557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the rectangle is too small for text, then return 35590a0f7f3b2ca79419d417626f11b119d5a8b92f45Michael Chan if (eventLayout == null || width < MIN_CELL_WIDTH_FOR_TEXT) { 3560f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan return; 3561f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 3562f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan 356308ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan int totalLineHeight = 0; 3564f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan int lineCount = eventLayout.getLineCount(); 3565f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan for (int i = 0; i < lineCount; i++) { 3566f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan int lineBottom = eventLayout.getLineBottom(i); 3567f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan if (lineBottom <= height) { 356808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan totalLineHeight = lineBottom; 356908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan } else { 357008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan break; 3571f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 3572f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan } 3573f63bf8348e504760a12d840c7107f326c0e2cadaMichael Chan 357408ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan if (totalLineHeight == 0 || rect.top > bottom || rect.top + totalLineHeight < top) { 3575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 35783e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh // Use a StaticLayout to format the string. 35793e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh canvas.save(); 35806ab3a2c7de3719a4806d6c9cd5b53cb34a5bb017Mindy Pereira // canvas.translate(rect.left, rect.top + (rect.bottom - rect.top / 2)); 35816ab3a2c7de3719a4806d6c9cd5b53cb34a5bb017Mindy Pereira int padding = center? (rect.bottom - rect.top - totalLineHeight) / 2 : 0; 35826ab3a2c7de3719a4806d6c9cd5b53cb34a5bb017Mindy Pereira canvas.translate(rect.left, rect.top + padding); 35831ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.left = 0; 35841ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.right = width; 35851ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan rect.top = 0; 358608ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan rect.bottom = totalLineHeight; 358708ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan 358808ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // There's a bug somewhere. If this rect is outside of a previous 358908ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // cliprect, this becomes a no-op. What happens is that the text draw 359008ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // past the event rect. The current fix is to not draw the staticLayout 359108ec68f143b718d300eb451047d3ba36dfae2e03Michael Chan // at all if it is completely out of bound. 35921ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan canvas.clipRect(rect); 35933e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh eventLayout.draw(canvas); 35943e7015267340b09d142dfcd3ff8acda257711023Shachar Shemesh canvas.restore(); 3595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3596146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 35971ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // This is to replace p.setStyle(Style.STROKE); canvas.drawRect() since it 35981ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan // doesn't work well with hardware acceleration 359921bd42039c92232647f54461cd20708224cc7eb6Michael Chan// private void drawEmptyRect(Canvas canvas, Rect r, int color) { 360021bd42039c92232647f54461cd20708224cc7eb6Michael Chan// int linesIndex = 0; 360121bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.left; 360221bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.top; 360321bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.right; 360421bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.top; 360521bd42039c92232647f54461cd20708224cc7eb6Michael Chan// 360621bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.left; 360721bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.bottom; 360821bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.right; 360921bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.bottom; 361021bd42039c92232647f54461cd20708224cc7eb6Michael Chan// 361121bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.left; 361221bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.top; 361321bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.left; 361421bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.bottom; 361521bd42039c92232647f54461cd20708224cc7eb6Michael Chan// 361621bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.right; 361721bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.top; 361821bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.right; 361921bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mLines[linesIndex++] = r.bottom; 362021bd42039c92232647f54461cd20708224cc7eb6Michael Chan// mPaint.setColor(color); 362121bd42039c92232647f54461cd20708224cc7eb6Michael Chan// canvas.drawLines(mLines, 0, linesIndex, mPaint); 362221bd42039c92232647f54461cd20708224cc7eb6Michael Chan// } 36231ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan 3624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void updateEventDetails() { 3625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent == null || mSelectionMode == SELECTION_HIDDEN 3626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project || mSelectionMode == SELECTION_LONGPRESS) { 3627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 3628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3630666fc5e8ddbac15c951aad738bd818ee307eae42Erik if (mLastPopupEventID == mSelectedEvent.id) { 3631666fc5e8ddbac15c951aad738bd818ee307eae42Erik return; 3632666fc5e8ddbac15c951aad738bd818ee307eae42Erik } 3633666fc5e8ddbac15c951aad738bd818ee307eae42Erik 3634666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = mSelectedEvent.id; 3635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Remove any outstanding callbacks to dismiss the popup. 3637ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.removeCallbacks(mDismissPopup); 3638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = mSelectedEvent; 3640146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView titleView = (TextView) mPopupView.findViewById(R.id.event_title); 3641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project titleView.setText(event.title); 3642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3643146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ImageView imageView = (ImageView) mPopupView.findViewById(R.id.reminder_icon); 3644146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView.setVisibility(event.hasAlarm ? View.VISIBLE : View.GONE); 3645146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView = (ImageView) mPopupView.findViewById(R.id.repeat_icon); 3647146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project imageView.setVisibility(event.isRepeating ? View.VISIBLE : View.GONE); 3648146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3649146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags; 3650146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.allDay) { 365146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan flags = DateUtils.FORMAT_UTC | DateUtils.FORMAT_SHOW_DATE 365246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_ALL; 3653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3654146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE 3655146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_ALL 3656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 3657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3658ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan if (DateFormat.is24HourFormat(mContext)) { 3659146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project flags |= DateUtils.FORMAT_24HOUR; 3660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 366146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan String timeRange = Utils.formatDateRange(mContext, event.startMillis, event.endMillis, 366246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan flags); 3663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView timeView = (TextView) mPopupView.findViewById(R.id.time); 3664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project timeView.setText(timeRange); 3665146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project TextView whereView = (TextView) mPopupView.findViewById(R.id.where); 3667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project final boolean empty = TextUtils.isEmpty(event.location); 3668146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project whereView.setVisibility(empty ? View.GONE : View.VISIBLE); 3669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!empty) whereView.setText(event.location); 3670146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.showAtLocation(this, Gravity.BOTTOM | Gravity.LEFT, mHoursWidth, 5); 3672ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.postDelayed(mDismissPopup, POPUP_DISMISS_DELAY); 3673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3674146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3675146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The following routines are called from the parent activity when certain 3676146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // touch events occur. 36774484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doDown(MotionEvent ev) { 3678146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_DOWN; 3679146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = 0; 3680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mOnFlingCalled = false; 3681ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.removeCallbacks(mContinueScroll); 3682056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson int x = (int) ev.getX(); 3683056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson int y = (int) ev.getY(); 3684056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson 3685056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // Save selection information: we use setSelectionFromPosition to find the selected event 3686056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // in order to show the "clicked" color. But since it is also setting the selected info 3687056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // for new events, we need to restore the old info after calling the function. 3688056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson Event oldSelectedEvent = mSelectedEvent; 3689056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson int oldSelectionDay = mSelectionDay; 3690056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson int oldSelectionHour = mSelectionHour; 3691989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson if (setSelectionFromPosition(x, y, false)) { 3692056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // If a time was selected (a blue selection box is visible) and the click location 3693056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // is in the selected time, do not show a click on an event to prevent a situation 3694056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // of both a selection and an event are clicked when they overlap. 3695989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson boolean pressedSelected = (mSelectionMode != SELECTION_HIDDEN) 3696056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson && oldSelectionDay == mSelectionDay && oldSelectionHour == mSelectionHour; 3697056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson if (!pressedSelected && mSelectedEvent != null) { 3698ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson mSavedClickedEvent = mSelectedEvent; 369931c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson mDownTouchTime = System.currentTimeMillis(); 3700ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson postDelayed (mSetClick,mOnDownDelay); 3701056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson } else { 3702ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson eventClickCleanup(); 3703056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson } 3704056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson } 3705056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson mSelectedEvent = oldSelectedEvent; 3706056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson mSelectionDay = oldSelectionDay; 3707056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson mSelectionHour = oldSelectionHour; 3708056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson invalidate(); 3709146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3710146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 37112fda24534978f55711526dbde747aa50d68dec40RoboErik // Kicks off all the animations when the expand allday area is tapped 37122fda24534978f55711526dbde747aa50d68dec40RoboErik private void doExpandAllDayClick() { 37132fda24534978f55711526dbde747aa50d68dec40RoboErik mShowAllAllDayEvents = !mShowAllAllDayEvents; 37142fda24534978f55711526dbde747aa50d68dec40RoboErik 37152fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator.setFrameDelay(0); 37162fda24534978f55711526dbde747aa50d68dec40RoboErik 37172fda24534978f55711526dbde747aa50d68dec40RoboErik // Determine the starting height 37182fda24534978f55711526dbde747aa50d68dec40RoboErik if (mAnimateDayHeight == 0) { 37192fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayHeight = mShowAllAllDayEvents ? 37202fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayHeight - (int) MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT : mAlldayHeight; 37212fda24534978f55711526dbde747aa50d68dec40RoboErik } 37222fda24534978f55711526dbde747aa50d68dec40RoboErik // Cancel current animations 37232fda24534978f55711526dbde747aa50d68dec40RoboErik mCancellingAnimations = true; 37242fda24534978f55711526dbde747aa50d68dec40RoboErik if (mAlldayAnimator != null) { 37252fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayAnimator.cancel(); 37262fda24534978f55711526dbde747aa50d68dec40RoboErik } 37272fda24534978f55711526dbde747aa50d68dec40RoboErik if (mAlldayEventAnimator != null) { 37282fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayEventAnimator.cancel(); 37292fda24534978f55711526dbde747aa50d68dec40RoboErik } 37302fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMoreAlldayEventsAnimator != null) { 37312fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsAnimator.cancel(); 37322fda24534978f55711526dbde747aa50d68dec40RoboErik } 37332fda24534978f55711526dbde747aa50d68dec40RoboErik mCancellingAnimations = false; 37342fda24534978f55711526dbde747aa50d68dec40RoboErik // get new animators 37352fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayAnimator = getAllDayAnimator(); 37362fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayEventAnimator = getAllDayEventAnimator(); 37372fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsAnimator = ObjectAnimator.ofInt(this, 37382fda24534978f55711526dbde747aa50d68dec40RoboErik "moreAllDayEventsTextAlpha", 37392fda24534978f55711526dbde747aa50d68dec40RoboErik mShowAllAllDayEvents ? MORE_EVENTS_MAX_ALPHA : 0, 37402fda24534978f55711526dbde747aa50d68dec40RoboErik mShowAllAllDayEvents ? 0 : MORE_EVENTS_MAX_ALPHA); 37412fda24534978f55711526dbde747aa50d68dec40RoboErik 37422fda24534978f55711526dbde747aa50d68dec40RoboErik // Set up delays and start the animators 37432fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayAnimator.setStartDelay(mShowAllAllDayEvents ? ANIMATION_SECONDARY_DURATION : 0); 37442fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayAnimator.start(); 37452fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsAnimator.setStartDelay(mShowAllAllDayEvents ? 0 : ANIMATION_DURATION); 37462fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsAnimator.setDuration(ANIMATION_SECONDARY_DURATION); 37472fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsAnimator.start(); 37482fda24534978f55711526dbde747aa50d68dec40RoboErik if (mAlldayEventAnimator != null) { 37492fda24534978f55711526dbde747aa50d68dec40RoboErik // This is the only animator that can return null, so check it 37502fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayEventAnimator 37512fda24534978f55711526dbde747aa50d68dec40RoboErik .setStartDelay(mShowAllAllDayEvents ? ANIMATION_SECONDARY_DURATION : 0); 37522fda24534978f55711526dbde747aa50d68dec40RoboErik mAlldayEventAnimator.start(); 37532fda24534978f55711526dbde747aa50d68dec40RoboErik } 37542fda24534978f55711526dbde747aa50d68dec40RoboErik } 37552fda24534978f55711526dbde747aa50d68dec40RoboErik 37562fda24534978f55711526dbde747aa50d68dec40RoboErik /** 37572fda24534978f55711526dbde747aa50d68dec40RoboErik * Figures out the initial heights for allDay events and space when 37582fda24534978f55711526dbde747aa50d68dec40RoboErik * a view is being set up. 37592fda24534978f55711526dbde747aa50d68dec40RoboErik */ 37602fda24534978f55711526dbde747aa50d68dec40RoboErik public void initAllDayHeights() { 37612fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents <= mMaxUnexpandedAlldayEventCount) { 37622fda24534978f55711526dbde747aa50d68dec40RoboErik return; 37632fda24534978f55711526dbde747aa50d68dec40RoboErik } 37642fda24534978f55711526dbde747aa50d68dec40RoboErik if (mShowAllAllDayEvents) { 37652fda24534978f55711526dbde747aa50d68dec40RoboErik int maxADHeight = mViewHeight - DAY_HEADER_HEIGHT - MIN_HOURS_HEIGHT; 37662fda24534978f55711526dbde747aa50d68dec40RoboErik maxADHeight = Math.min(maxADHeight, 37672fda24534978f55711526dbde747aa50d68dec40RoboErik (int)(mMaxAlldayEvents * MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT)); 37682fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayEventHeight = maxADHeight / mMaxAlldayEvents; 37692fda24534978f55711526dbde747aa50d68dec40RoboErik } else { 37702fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayEventHeight = (int)MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT; 37712fda24534978f55711526dbde747aa50d68dec40RoboErik } 37722fda24534978f55711526dbde747aa50d68dec40RoboErik } 37732fda24534978f55711526dbde747aa50d68dec40RoboErik 37742fda24534978f55711526dbde747aa50d68dec40RoboErik // Sets up an animator for changing the height of allday events 37752fda24534978f55711526dbde747aa50d68dec40RoboErik private ObjectAnimator getAllDayEventAnimator() { 37762fda24534978f55711526dbde747aa50d68dec40RoboErik // First calculate the absolute max height 37772fda24534978f55711526dbde747aa50d68dec40RoboErik int maxADHeight = mViewHeight - DAY_HEADER_HEIGHT - MIN_HOURS_HEIGHT; 37782fda24534978f55711526dbde747aa50d68dec40RoboErik // Now expand to fit but not beyond the absolute max 37792fda24534978f55711526dbde747aa50d68dec40RoboErik maxADHeight = 37802fda24534978f55711526dbde747aa50d68dec40RoboErik Math.min(maxADHeight, (int)(mMaxAlldayEvents * MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT)); 37812fda24534978f55711526dbde747aa50d68dec40RoboErik // calculate the height of individual events in order to fit 37822fda24534978f55711526dbde747aa50d68dec40RoboErik int fitHeight = maxADHeight / mMaxAlldayEvents; 37832fda24534978f55711526dbde747aa50d68dec40RoboErik int currentHeight = mAnimateDayEventHeight; 37842fda24534978f55711526dbde747aa50d68dec40RoboErik int desiredHeight = 37852fda24534978f55711526dbde747aa50d68dec40RoboErik mShowAllAllDayEvents ? fitHeight : (int)MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT; 37862fda24534978f55711526dbde747aa50d68dec40RoboErik // if there's nothing to animate just return 37872fda24534978f55711526dbde747aa50d68dec40RoboErik if (currentHeight == desiredHeight) { 37882fda24534978f55711526dbde747aa50d68dec40RoboErik return null; 37892fda24534978f55711526dbde747aa50d68dec40RoboErik } 37902fda24534978f55711526dbde747aa50d68dec40RoboErik 37912fda24534978f55711526dbde747aa50d68dec40RoboErik // Set up the animator with the calculated values 37922fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator animator = ObjectAnimator.ofInt(this, "animateDayEventHeight", 37932fda24534978f55711526dbde747aa50d68dec40RoboErik currentHeight, desiredHeight); 37942fda24534978f55711526dbde747aa50d68dec40RoboErik animator.setDuration(ANIMATION_DURATION); 37952fda24534978f55711526dbde747aa50d68dec40RoboErik return animator; 37962fda24534978f55711526dbde747aa50d68dec40RoboErik } 37972fda24534978f55711526dbde747aa50d68dec40RoboErik 37982fda24534978f55711526dbde747aa50d68dec40RoboErik // Sets up an animator for changing the height of the allday area 37992fda24534978f55711526dbde747aa50d68dec40RoboErik private ObjectAnimator getAllDayAnimator() { 38002fda24534978f55711526dbde747aa50d68dec40RoboErik // Calculate the absolute max height 38012fda24534978f55711526dbde747aa50d68dec40RoboErik int maxADHeight = mViewHeight - DAY_HEADER_HEIGHT - MIN_HOURS_HEIGHT; 38022fda24534978f55711526dbde747aa50d68dec40RoboErik // Find the desired height but don't exceed abs max 38032fda24534978f55711526dbde747aa50d68dec40RoboErik maxADHeight = 38042fda24534978f55711526dbde747aa50d68dec40RoboErik Math.min(maxADHeight, (int)(mMaxAlldayEvents * MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT)); 38052fda24534978f55711526dbde747aa50d68dec40RoboErik // calculate the current and desired heights 38062fda24534978f55711526dbde747aa50d68dec40RoboErik int currentHeight = mAnimateDayHeight != 0 ? mAnimateDayHeight : mAlldayHeight; 38072fda24534978f55711526dbde747aa50d68dec40RoboErik int desiredHeight = mShowAllAllDayEvents ? maxADHeight : 38082fda24534978f55711526dbde747aa50d68dec40RoboErik (int) (MAX_UNEXPANDED_ALLDAY_HEIGHT - MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT - 1); 38092fda24534978f55711526dbde747aa50d68dec40RoboErik 38102fda24534978f55711526dbde747aa50d68dec40RoboErik // Set up the animator with the calculated values 38112fda24534978f55711526dbde747aa50d68dec40RoboErik ObjectAnimator animator = ObjectAnimator.ofInt(this, "animateDayHeight", 38122fda24534978f55711526dbde747aa50d68dec40RoboErik currentHeight, desiredHeight); 38132fda24534978f55711526dbde747aa50d68dec40RoboErik animator.setDuration(ANIMATION_DURATION); 38142fda24534978f55711526dbde747aa50d68dec40RoboErik 38152fda24534978f55711526dbde747aa50d68dec40RoboErik animator.addListener(new AnimatorListenerAdapter() { 38162fda24534978f55711526dbde747aa50d68dec40RoboErik @Override 38172fda24534978f55711526dbde747aa50d68dec40RoboErik public void onAnimationEnd(Animator animation) { 38182fda24534978f55711526dbde747aa50d68dec40RoboErik if (!mCancellingAnimations) { 38192fda24534978f55711526dbde747aa50d68dec40RoboErik // when finished, set this to 0 to signify not animating 38202fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayHeight = 0; 3821cbc6ad106295bad0bef29cb51a2dfb56be9d6bcdRoboErik mUseExpandIcon = !mShowAllAllDayEvents; 38222fda24534978f55711526dbde747aa50d68dec40RoboErik } 38232fda24534978f55711526dbde747aa50d68dec40RoboErik mRemeasure = true; 38242fda24534978f55711526dbde747aa50d68dec40RoboErik invalidate(); 38252fda24534978f55711526dbde747aa50d68dec40RoboErik } 38262fda24534978f55711526dbde747aa50d68dec40RoboErik }); 38272fda24534978f55711526dbde747aa50d68dec40RoboErik return animator; 38282fda24534978f55711526dbde747aa50d68dec40RoboErik } 38292fda24534978f55711526dbde747aa50d68dec40RoboErik 38302fda24534978f55711526dbde747aa50d68dec40RoboErik // setter for the 'box +n' alpha text used by the animator 38312fda24534978f55711526dbde747aa50d68dec40RoboErik public void setMoreAllDayEventsTextAlpha(int alpha) { 38322fda24534978f55711526dbde747aa50d68dec40RoboErik mMoreAlldayEventsTextAlpha = alpha; 38332fda24534978f55711526dbde747aa50d68dec40RoboErik invalidate(); 38342fda24534978f55711526dbde747aa50d68dec40RoboErik } 38352fda24534978f55711526dbde747aa50d68dec40RoboErik 38362fda24534978f55711526dbde747aa50d68dec40RoboErik // setter for the height of the allday area used by the animator 38372fda24534978f55711526dbde747aa50d68dec40RoboErik public void setAnimateDayHeight(int height) { 38382fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayHeight = height; 38392fda24534978f55711526dbde747aa50d68dec40RoboErik mRemeasure = true; 38402fda24534978f55711526dbde747aa50d68dec40RoboErik invalidate(); 38412fda24534978f55711526dbde747aa50d68dec40RoboErik } 38422fda24534978f55711526dbde747aa50d68dec40RoboErik 38432fda24534978f55711526dbde747aa50d68dec40RoboErik // setter for the height of allday events used by the animator 38442fda24534978f55711526dbde747aa50d68dec40RoboErik public void setAnimateDayEventHeight(int height) { 38452fda24534978f55711526dbde747aa50d68dec40RoboErik mAnimateDayEventHeight = height; 38462fda24534978f55711526dbde747aa50d68dec40RoboErik mRemeasure = true; 38472fda24534978f55711526dbde747aa50d68dec40RoboErik invalidate(); 38482fda24534978f55711526dbde747aa50d68dec40RoboErik } 38492fda24534978f55711526dbde747aa50d68dec40RoboErik 38504484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doSingleTapUp(MotionEvent ev) { 3851bbf2cbdb040108da50d763b699836e5f63fb7cceMichael Chan if (!mHandleActionUp || mScrolling) { 3852d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return; 3853d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3854d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 3855146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int x = (int) ev.getX(); 3856146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int y = (int) ev.getY(); 3857146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectedDay = mSelectionDay; 3858146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int selectedHour = mSelectionHour; 3859146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 38602fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount) { 38612fda24534978f55711526dbde747aa50d68dec40RoboErik // check if the tap was in the allday expansion area 38624ab51bf9fc2f3e6915705f39688e8244fc74028fRoboErik int bottom = mFirstCell; 38632fda24534978f55711526dbde747aa50d68dec40RoboErik if((x < mHoursWidth && y > DAY_HEADER_HEIGHT && y < DAY_HEADER_HEIGHT + mAlldayHeight) 38642fda24534978f55711526dbde747aa50d68dec40RoboErik || (!mShowAllAllDayEvents && mAnimateDayHeight == 0 && y < bottom && 38652fda24534978f55711526dbde747aa50d68dec40RoboErik y >= bottom - MIN_UNEXPANDED_ALLDAY_EVENT_HEIGHT)) { 38662fda24534978f55711526dbde747aa50d68dec40RoboErik doExpandAllDayClick(); 38672fda24534978f55711526dbde747aa50d68dec40RoboErik return; 38682fda24534978f55711526dbde747aa50d68dec40RoboErik } 38692fda24534978f55711526dbde747aa50d68dec40RoboErik } 38702fda24534978f55711526dbde747aa50d68dec40RoboErik 3871989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson boolean validPosition = setSelectionFromPosition(x, y, false); 3872146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!validPosition) { 3873360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan if (y < DAY_HEADER_HEIGHT) { 3874360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan Time selectedTime = new Time(mBaseDate); 3875360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan selectedTime.setJulianDay(mSelectionDay); 3876360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan selectedTime.hour = mSelectionHour; 3877360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan selectedTime.normalize(true /* ignore isDst */); 3878360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan mController.sendEvent(this, EventType.GO_TO, null, null, selectedTime, -1, 3879360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan ViewType.DAY, CalendarController.EXTRA_GOTO_DATE, null, null); 3880360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan } 3881146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 3882146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3883146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3884b6fb51224b578b26e503fddae2799d03a2aaad47RoboErik boolean hasSelection = mSelectionMode != SELECTION_HIDDEN; 388595f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan boolean pressedSelected = (hasSelection || mTouchExplorationEnabled) 388695f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan && selectedDay == mSelectionDay && selectedHour == mSelectionHour; 3887146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3888989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson if (pressedSelected && mSavedClickedEvent == null) { 3889344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan // If the tap is on an already selected hour slot, then create a new 3890344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan // event 3891edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan long extraLong = 0; 3892edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan if (mSelectionAllday) { 3893edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan extraLong = CalendarController.EXTRA_CREATE_ALL_DAY; 3894edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan } 389595f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan mSelectionMode = SELECTION_SELECTED; 3896edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan mController.sendEventRelatedEventWithExtra(this, EventType.CREATE_EVENT, -1, 3897edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan getSelectedTimeInMillis(), 0, (int) ev.getRawX(), (int) ev.getRawY(), 3898edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan extraLong, -1); 389995f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan } else if (mSelectedEvent != null) { 390095f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan // If the tap is on an event, launch the "View event" view 390195f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan if (mIsAccessibilityEnabled) { 390295f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan mAccessibilityMgr.interrupt(); 390395f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan } 390495f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan 390595f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan mSelectionMode = SELECTION_HIDDEN; 39060aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson 39070aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson int yLocation = 39080aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson (int)((mSelectedEvent.top + mSelectedEvent.bottom)/2); 39090aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson // Y location is affected by the position of the event in the scrolling 39100aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson // view (mViewStartY) and the presence of all day events (mFirstCell) 39110aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson if (!mSelectedEvent.allDay) { 39120aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson yLocation += (mFirstCell - mViewStartY); 39130aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson } 3914056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson mClickedYLocation = yLocation; 391531c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson long clearDelay = (CLICK_DISPLAY_DURATION + mOnDownDelay) - 391631c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson (System.currentTimeMillis() - mDownTouchTime); 391731c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson if (clearDelay > 0) { 391831c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson this.postDelayed(mClearClick, clearDelay); 391931c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson } else { 392031c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson this.post(mClearClick); 392131c7812de1b56561e56f2af6928debd66e4a9124Isaac Katzenelson } 3922344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan } else { 392395f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan // Select time 3924344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan Time startTime = new Time(mBaseDate); 3925344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.setJulianDay(mSelectionDay); 3926344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.hour = mSelectionHour; 3927344c69e88c32ea40386c40d420c83bece9c2d556Michael Chan startTime.normalize(true /* ignore isDst */); 392883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 392983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Time endTime = new Time(startTime); 393083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan endTime.hour++; 393183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 393295f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan mSelectionMode = SELECTION_SELECTED; 393346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mController.sendEvent(this, EventType.GO_TO, startTime, endTime, -1, ViewType.CURRENT, 393446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan CalendarController.EXTRA_GOTO_TIME, null, null); 3935146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 393695f745f00303b00549a1d59d8ccb0b82ea91c17cMichael Chan invalidate(); 3937146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3938146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 39394484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doLongPress(MotionEvent ev) { 3940ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson eventClickCleanup(); 3941bbf2cbdb040108da50d763b699836e5f63fb7cceMichael Chan if (mScrolling) { 3942bbf2cbdb040108da50d763b699836e5f63fb7cceMichael Chan return; 3943bbf2cbdb040108da50d763b699836e5f63fb7cceMichael Chan } 3944bbf2cbdb040108da50d763b699836e5f63fb7cceMichael Chan 3945d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // Scale gesture in progress 3946d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mStartingSpanY != 0) { 3947d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return; 3948d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 3949d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 395080bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan int x = (int) ev.getX(); 395180bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan int y = (int) ev.getY(); 395280bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan 3953989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson boolean validPosition = setSelectionFromPosition(x, y, false); 395480bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan if (!validPosition) { 395580bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan // return if the touch wasn't on an area of concern 395680bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan return; 395780bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan } 395880bbecfb183210ccbe53ec99e8b3d9aab323da2bMichael Chan 3959146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 3960146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 3961146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project performLongClick(); 3962146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3963146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 39644484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan private void doScroll(MotionEvent e1, MotionEvent e2, float deltaX, float deltaY) { 396595d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan cancelAnimation(); 39664f58287a1e02325337e39073a50bbb880094099fRoboErik if (mStartingScroll) { 39674f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollX = 0; 39684f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollY = 0; 39694f58287a1e02325337e39073a50bbb880094099fRoboErik mStartingScroll = false; 39704f58287a1e02325337e39073a50bbb880094099fRoboErik } 39716d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 39724f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollX += deltaX; 39734f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollY += deltaY; 39744f58287a1e02325337e39073a50bbb880094099fRoboErik int distanceX = (int) mInitialScrollX; 39754f58287a1e02325337e39073a50bbb880094099fRoboErik int distanceY = (int) mInitialScrollY; 3976146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3977146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If we haven't figured out the predominant scroll direction yet, 3978146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // then do it now. 3979146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mTouchMode == TOUCH_MODE_DOWN) { 3980146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int absDistanceX = Math.abs(distanceX); 3981146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int absDistanceY = Math.abs(distanceY); 3982146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrollStartY = mViewStartY; 3983146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPreviousDirection = 0; 3984146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 3985f9a2842a66fe858336144ba87c668efc2e18a9acMichael Chan if (absDistanceX > absDistanceY) { 3986146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_HSCROLL; 3987146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = distanceX; 3988146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initNextView(-mViewStartX); 3989146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 3990146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mTouchMode = TOUCH_MODE_VSCROLL; 3991146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 3992146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 3993146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // We are already scrolling horizontally, so check if we 3994146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // changed the direction of scrolling so that the other week 3995146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // is now visible. 3996146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = distanceX; 3997146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (distanceX != 0) { 3998146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int direction = (distanceX > 0) ? 1 : -1; 3999146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (direction != mPreviousDirection) { 4000146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // The user has switched the direction of scrolling 4001146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // so re-init the next view 4002146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initNextView(-mViewStartX); 4003146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPreviousDirection = direction; 4004146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4005146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4006146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4007146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4008146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if ((mTouchMode & TOUCH_MODE_VSCROLL) != 0) { 4009146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mScrollStartY + distanceY; 4010433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 4011433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // If dragging while already at the end, do a glow 4012433ba924de1ac26b923e2beb061812012749e4f3Michael Chan final int pulledToY = (int) (mScrollStartY + deltaY); 4013433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (pulledToY < 0) { 4014433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop.onPull(deltaY / mViewHeight); 4015433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (!mEdgeEffectBottom.isFinished()) { 4016433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom.onRelease(); 4017433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4018433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } else if (pulledToY > mMaxViewStartY) { 4019433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom.onPull(deltaY / mViewHeight); 4020433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (!mEdgeEffectTop.isFinished()) { 4021433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop.onRelease(); 4022433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4023433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4024433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 4025146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mViewStartY < 0) { 4026146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = 0; 4027146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mViewStartY > mMaxViewStartY) { 4028146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartY = mMaxViewStartY; 4029146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4030146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeFirstHour(); 4031146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4032146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4033146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = true; 4034146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4035d9dbab823d56bf596eedaecd0935037bd39d02c1Michael Chan mSelectionMode = SELECTION_HIDDEN; 4036146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 4037146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4038146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4039f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan private void cancelAnimation() { 4040f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan Animation in = mViewSwitcher.getInAnimation(); 4041f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan if (in != null) { 404295d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan // cancel() doesn't terminate cleanly. 404395d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan in.scaleCurrentDuration(0); 40446d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } 4045f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan Animation out = mViewSwitcher.getOutAnimation(); 4046f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan if (out != null) { 404795d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan // cancel() doesn't terminate cleanly. 404895d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan out.scaleCurrentDuration(0); 4049f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan } 4050f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan } 4051f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan 4052f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan private void doFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 4053f6c785f1dacb26523f229e1b06e3a4eb6fa4ff0dMichael Chan cancelAnimation(); 40546d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan 4055146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_HIDDEN; 4056ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson eventClickCleanup(); 4057056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson 4058146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mOnFlingCalled = true; 405990a68379c01137781249156742cfc9ba21684b83Michael Chan 406090a68379c01137781249156742cfc9ba21684b83Michael Chan if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 4061030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown // Horizontal fling. 406211638ad4fb56b978770aebe75deac7a0e6ac60d2Erik // initNextView(deltaX); 406390a68379c01137781249156742cfc9ba21684b83Michael Chan mTouchMode = TOUCH_MODE_INITIAL_STATE; 406490a68379c01137781249156742cfc9ba21684b83Michael Chan if (DEBUG) Log.d(TAG, "doFling: velocityX " + velocityX); 406590a68379c01137781249156742cfc9ba21684b83Michael Chan int deltaX = (int) e2.getX() - (int) e1.getX(); 40662c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan switchViews(deltaX < 0, mViewStartX, mViewWidth, velocityX); 4067146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mViewStartX = 0; 4068146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 4069146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4070146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 407190a68379c01137781249156742cfc9ba21684b83Michael Chan if ((mTouchMode & TOUCH_MODE_VSCROLL) == 0) { 407290a68379c01137781249156742cfc9ba21684b83Michael Chan if (DEBUG) Log.d(TAG, "doFling: no fling"); 407390a68379c01137781249156742cfc9ba21684b83Michael Chan return; 407490a68379c01137781249156742cfc9ba21684b83Michael Chan } 407590a68379c01137781249156742cfc9ba21684b83Michael Chan 4076030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown // Vertical fling. 407790a68379c01137781249156742cfc9ba21684b83Michael Chan mTouchMode = TOUCH_MODE_INITIAL_STATE; 4078030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown mViewStartX = 0; 4079030803e32522be52a1ddeb436edbd024942d7c4fDavid Brown 40803f6328f579b05c02606572c777541b97aa04f9f3Michael Chan if (DEBUG) { 40813f6328f579b05c02606572c777541b97aa04f9f3Michael Chan Log.d(TAG, "doFling: mViewStartY" + mViewStartY + " velocityY " + velocityY); 40823f6328f579b05c02606572c777541b97aa04f9f3Michael Chan } 40833f6328f579b05c02606572c777541b97aa04f9f3Michael Chan 4084146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Continue scrolling vertically 40853f6328f579b05c02606572c777541b97aa04f9f3Michael Chan mScrolling = true; 40863f6328f579b05c02606572c777541b97aa04f9f3Michael Chan mScroller.fling(0 /* startX */, mViewStartY /* startY */, 0 /* velocityX */, 4087433ba924de1ac26b923e2beb061812012749e4f3Michael Chan (int) -velocityY, 0 /* minX */, 0 /* maxX */, 0 /* minY */, 4088433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mMaxViewStartY /* maxY */, OVERFLING_DISTANCE, OVERFLING_DISTANCE); 4089433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 4090433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // When flinging down, show a glow when it hits the end only if it 4091433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // wasn't started at the top 4092433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (velocityY > 0 && mViewStartY != 0) { 4093433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mCallEdgeEffectOnAbsorb = true; 4094433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4095433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // When flinging up, show a glow when it hits the end only if it wasn't 4096433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // started at the bottom 4097433ba924de1ac26b923e2beb061812012749e4f3Michael Chan else if (velocityY < 0 && mViewStartY != mMaxViewStartY) { 4098433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mCallEdgeEffectOnAbsorb = true; 4099433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4100ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.post(mContinueScroll); 4101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private boolean initNextView(int deltaX) { 4104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Change the view to the previous day or week 4105d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView view = (DayView) mViewSwitcher.getNextView(); 4106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Time date = view.mBaseDate; 4107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.set(mBaseDate); 4108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project boolean switchForward; 4109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (deltaX > 0) { 4110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay -= mNumDays; 4111989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson view.setSelectedDay(mSelectionDay - mNumDays); 4112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchForward = false; 4113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.monthDay += mNumDays; 4115989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson view.setSelectedDay(mSelectionDay + mNumDays); 4116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switchForward = true; 4117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project date.normalize(true /* ignore isDst */); 4119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project initView(view); 4120ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan view.layout(getLeft(), getTop(), getRight(), getBottom()); 4121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project view.reloadEvents(); 4122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return switchForward; 4123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4125d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 4126d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public boolean onScaleBegin(ScaleGestureDetector detector) { 4127d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = false; 41282fda24534978f55711526dbde747aa50d68dec40RoboErik float gestureCenterInPixels = detector.getFocusY() - DAY_HEADER_HEIGHT - mAlldayHeight; 4129d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) / (mCellHeight + DAY_GAP); 4130d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4131d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = Math.max(MIN_Y_SPAN, Math.abs(detector.getCurrentSpanY())); 4132d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = mCellHeight; 4133d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 41349ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG_SCALING) { 4135d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float ViewStartHour = mViewStartY / (float) (mCellHeight + DAY_GAP); 41366f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan Log.d(TAG, "onScaleBegin: mGestureCenterHour:" + mGestureCenterHour 41376f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan + "\tViewStartHour: " + ViewStartHour + "\tmViewStartY:" + mViewStartY 41386f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan + "\tmCellHeight:" + mCellHeight + " SpanY:" + detector.getCurrentSpanY()); 4139d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4140d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4141d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 4142d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4143d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4144d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 4145d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public boolean onScale(ScaleGestureDetector detector) { 41466f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan float spanY = Math.max(MIN_Y_SPAN, Math.abs(detector.getCurrentSpanY())); 4147d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4148d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = (int) (mCellHeightBeforeScaleGesture * spanY / mStartingSpanY); 4149d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4150d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mCellHeight < mMinCellHeight) { 4151d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // If mStartingSpanY is too small, even a small increase in the 4152d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // gesture can bump the mCellHeight beyond MAX_CELL_HEIGHT 41536f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan mStartingSpanY = spanY; 4154d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = mMinCellHeight; 4155d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = mMinCellHeight; 4156d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } else if (mCellHeight > MAX_CELL_HEIGHT) { 4157d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = spanY; 4158d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight = MAX_CELL_HEIGHT; 4159d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeightBeforeScaleGesture = MAX_CELL_HEIGHT; 4160d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4161d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 41622fda24534978f55711526dbde747aa50d68dec40RoboErik int gestureCenterInPixels = (int) detector.getFocusY() - DAY_HEADER_HEIGHT - mAlldayHeight; 4163d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = (int) (mGestureCenterHour * (mCellHeight + DAY_GAP)) - gestureCenterInPixels; 4164d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mMaxViewStartY = HOUR_GAP + 24 * (mCellHeight + HOUR_GAP) - mGridAreaHeight; 4165d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 41669ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG_SCALING) { 4167d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan float ViewStartHour = mViewStartY / (float) (mCellHeight + DAY_GAP); 41686f5fc3bf685b396da65290d32dd4744aa7a9fc9dMichael Chan Log.d(TAG, "onScale: mGestureCenterHour:" + mGestureCenterHour + "\tViewStartHour: " 4169d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + ViewStartHour + "\tmViewStartY:" + mViewStartY + "\tmCellHeight:" 4170d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan + mCellHeight + " SpanY:" + detector.getCurrentSpanY()); 4171d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4172d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4173d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan if (mViewStartY < 0) { 4174d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = 0; 4175d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) 4176d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan / (float) (mCellHeight + DAY_GAP); 4177d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } else if (mViewStartY > mMaxViewStartY) { 4178d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mViewStartY = mMaxViewStartY; 4179d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mGestureCenterHour = (mViewStartY + gestureCenterInPixels) 4180d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan / (float) (mCellHeight + DAY_GAP); 4181d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4182d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan computeFirstHour(); 4183d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4184d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mRemeasure = true; 4185d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan invalidate(); 4186d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 4187d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4188d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4189d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan // ScaleGestureDetector.OnScaleGestureListener 4190d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan public void onScaleEnd(ScaleGestureDetector detector) { 41914f58287a1e02325337e39073a50bbb880094099fRoboErik mScrollStartY = mViewStartY; 41924f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollY = 0; 41934f58287a1e02325337e39073a50bbb880094099fRoboErik mInitialScrollX = 0; 4194d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mStartingSpanY = 0; 4195d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4196d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project @Override 4198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onTouchEvent(MotionEvent ev) { 4199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int action = ev.getAction(); 42009ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "" + action + " ev.getPointerCount() = " + ev.getPointerCount()); 4201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 42021ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan if ((mTouchMode & TOUCH_MODE_HSCROLL) == 0) { 42031ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan mScaleGestureDetector.onTouchEvent(ev); 42041ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan if (mScaleGestureDetector.isInProgress()) { 42051ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan return true; 42061ba48526c2542484d91383c21d3d8e07db87df0fMichael Chan } 4207d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan } 4208d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan 4209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (action) { 421046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_DOWN: 42114f58287a1e02325337e39073a50bbb880094099fRoboErik mStartingScroll = true; 42129ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) { 42139ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan Log.e(TAG, "ACTION_DOWN ev.getDownTime = " + ev.getDownTime() + " Cnt=" 42149ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan + ev.getPointerCount()); 42159ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan } 42169ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 42172fda24534978f55711526dbde747aa50d68dec40RoboErik int bottom = mAlldayHeight + DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 42182fda24534978f55711526dbde747aa50d68dec40RoboErik if (ev.getY() < bottom) { 42192fda24534978f55711526dbde747aa50d68dec40RoboErik mTouchStartedInAlldayArea = true; 42202fda24534978f55711526dbde747aa50d68dec40RoboErik } else { 42212fda24534978f55711526dbde747aa50d68dec40RoboErik mTouchStartedInAlldayArea = false; 42222fda24534978f55711526dbde747aa50d68dec40RoboErik } 4223d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mHandleActionUp = true; 422446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 4225d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan return true; 422646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 422746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_MOVE: 42289ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "ACTION_MOVE Cnt=" + ev.getPointerCount() + DayView.this); 422946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 4230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 423146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 423246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_UP: 42339ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "ACTION_UP Cnt=" + ev.getPointerCount() + mHandleActionUp); 4234433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop.onRelease(); 4235433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom.onRelease(); 42364f58287a1e02325337e39073a50bbb880094099fRoboErik mStartingScroll = false; 423746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 423846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (!mHandleActionUp) { 423946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mHandleActionUp = true; 424057756df22153a2c0155a4e743c8a658caa8ada33RoboErik mViewStartX = 0; 424157756df22153a2c0155a4e743c8a658caa8ada33RoboErik invalidate(); 42427abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project return true; 424346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 4244befa15c0a47a744a7c28a9be7b079a93e195c833Isaac Katzenelson 4245befa15c0a47a744a7c28a9be7b079a93e195c833Isaac Katzenelson if (mOnFlingCalled) { 4246befa15c0a47a744a7c28a9be7b079a93e195c833Isaac Katzenelson return true; 4247befa15c0a47a744a7c28a9be7b079a93e195c833Isaac Katzenelson } 4248befa15c0a47a744a7c28a9be7b079a93e195c833Isaac Katzenelson 4249056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // If we were scrolling, then reset the selected hour so that it 4250056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // is visible. 4251056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson if (mScrolling) { 4252056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson mScrolling = false; 4253056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson resetSelectedHour(); 4254056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson invalidate(); 4255056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson } 425684fbd42c4ea8bae2a0edbd49333cb7112bf3cd51Isaac Katzenelson 425746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if ((mTouchMode & TOUCH_MODE_HSCROLL) != 0) { 425846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mTouchMode = TOUCH_MODE_INITIAL_STATE; 425946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (Math.abs(mViewStartX) > mHorizontalSnapBackThreshold) { 426046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // The user has gone beyond the threshold so switch views 426146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.d(TAG, "- horizontal scroll: switch views"); 42622c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan switchViews(mViewStartX > 0, mViewStartX, mViewWidth, 0); 426346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mViewStartX = 0; 426446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 426546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 426646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // Not beyond the threshold so invalidate which will cause 426746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // the view to snap back. Also call recalc() to ensure 426846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // that we have the correct starting date and title. 426946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.d(TAG, "- horizontal scroll: snap back"); 427046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan recalc(); 427146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan invalidate(); 427246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mViewStartX = 0; 427346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 427446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 427546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 427646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 4277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 427846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // This case isn't expected to happen. 427946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan case MotionEvent.ACTION_CANCEL: 428046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (DEBUG) Log.e(TAG, "ACTION_CANCEL"); 428146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan mGestureDetector.onTouchEvent(ev); 4282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mScrolling = false; 4283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project resetSelectedHour(); 4284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 428546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 428646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan default: 42879ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "Not MotionEvent " + ev.toString()); 428846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (mGestureDetector.onTouchEvent(ev)) { 428946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return true; 429046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 429146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan return super.onTouchEvent(ev); 4292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { 4296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project MenuItem item; 4297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the trackball is held down, then the context menu pops up and 429946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // we never get onKeyUp() for the long-press. So check for it here 4300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // and change the selection to the long-press state. 4301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionMode != SELECTION_LONGPRESS) { 4302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectionMode = SELECTION_LONGPRESS; 4303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 4304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4306e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan final long startMillis = getSelectedTimeInMillis(); 4307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int flags = DateUtils.FORMAT_SHOW_TIME 4308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_CAP_NOON_MIDNIGHT 4309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project | DateUtils.FORMAT_SHOW_WEEKDAY; 4310c5f92d7bdeb1950ace783cc022aa41a4b4f00cd6Erik final String title = Utils.formatDateRange(mContext, startMillis, startMillis, flags); 4311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project menu.setHeaderTitle(title); 4312e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numSelectedEvents = mSelectedEvents.size(); 4314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mNumDays == 1) { 4315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Day view. 4316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is a selected event, then allow it to be viewed and 4318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // edited. 4319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (numSelectedEvents >= 1) { 43204484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_VIEW, 0, R.string.event_view); 4321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_info_details); 4323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4324ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan int accessLevel = getEventAccessLevel(mContext, mSelectedEvent); 4325a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel == ACCESS_LEVEL_EDIT) { 43264484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_EDIT, 0, R.string.event_edit); 4327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_edit); 4329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('e'); 4330a505627659f6bfba8869eac8089f7030f2d0d92cErik } 4331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4332a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel >= ACCESS_LEVEL_DELETE) { 43334484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_DELETE, 0, R.string.event_delete); 4334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_delete); 4336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 43384484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 4339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_add); 4341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('n'); 4342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Otherwise, if the user long-pressed on a blank hour, allow 434446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // them to create an event. They can also do this by tapping. 43454484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 4346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_add); 4348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('n'); 4349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Week view. 4352e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there is a selected event, then allow it to be viewed and 4354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // edited. 4355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (numSelectedEvents >= 1) { 43564484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_VIEW, 0, R.string.event_view); 4357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_info_details); 4359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4360ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan int accessLevel = getEventAccessLevel(mContext, mSelectedEvent); 4361a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel == ACCESS_LEVEL_EDIT) { 43624484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_EDIT, 0, R.string.event_edit); 4363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_edit); 4365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setAlphabeticShortcut('e'); 4366a505627659f6bfba8869eac8089f7030f2d0d92cErik } 4367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4368a505627659f6bfba8869eac8089f7030f2d0d92cErik if (accessLevel >= ACCESS_LEVEL_DELETE) { 43694484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_DELETE, 0, R.string.event_delete); 4370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setOnMenuItemClickListener(mContextMenuHandler); 4371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project item.setIcon(android.R.drawable.ic_menu_delete); 4372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 43734484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan } 4374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 43754484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_EVENT_CREATE, 0, R.string.event_create); 43764484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 43774484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_add); 43784484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('n'); 4379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 43804484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item = menu.add(0, MENU_DAY, 0, R.string.show_day_view); 43814484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setOnMenuItemClickListener(mContextMenuHandler); 43824484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setIcon(android.R.drawable.ic_menu_day); 43834484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan item.setAlphabeticShortcut('d'); 4384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 4387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private class ContextMenuHandler implements MenuItem.OnMenuItemClickListener { 4390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public boolean onMenuItemClick(MenuItem item) { 4391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project switch (item.getItemId()) { 43924484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_VIEW: { 4393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 4394a7694eead7cbb293990bc89c3906e17bad36194cErik mController.sendEventRelatedEvent(this, EventType.VIEW_EVENT_DETAILS, 43959e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.id, mSelectedEvent.startMillis, 439687f993ff96172f508d3f241f8a425f953c7eb739RoboErik mSelectedEvent.endMillis, 0, 0, -1); 4397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 44004484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_EDIT: { 4401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 44029e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.EDIT_EVENT, 44039e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mSelectedEvent.id, mSelectedEvent.startMillis, 440487f993ff96172f508d3f241f8a425f953c7eb739RoboErik mSelectedEvent.endMillis, 0, 0, -1); 4405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 44084484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_DAY: { 4409487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mController.sendEvent(this, EventType.GO_TO, getSelectedTime(), null, -1, 44109e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan ViewType.DAY); 4411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 44134484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_AGENDA: { 4414487552be8ae3c1b148211c0fbf594d2b73727fd6Michael Chan mController.sendEvent(this, EventType.GO_TO, getSelectedTime(), null, -1, 44159e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan ViewType.AGENDA); 4416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 44184484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_CREATE: { 4419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long startMillis = getSelectedTimeInMillis(); 4420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long endMillis = startMillis + DateUtils.HOUR_IN_MILLIS; 44219e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 442287f993ff96172f508d3f241f8a425f953c7eb739RoboErik startMillis, endMillis, 0, 0, -1); 4423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 44254484b04707d5570a6de4a5a4b228a9bb273bbab7Michael Chan case MENU_EVENT_DELETE: { 4426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent != null) { 4427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event selectedEvent = mSelectedEvent; 4428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long begin = selectedEvent.startMillis; 4429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long end = selectedEvent.endMillis; 4430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long id = selectedEvent.id; 44319e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan mController.sendEventRelatedEvent(this, EventType.DELETE_EVENT, id, begin, 443287f993ff96172f508d3f241f8a425f953c7eb739RoboErik end, 0, 0, -1); 4433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project default: { 4437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return false; 4438146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 4441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4444a505627659f6bfba8869eac8089f7030f2d0d92cErik private static int getEventAccessLevel(Context context, Event e) { 4445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project ContentResolver cr = context.getContentResolver(); 4446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4447ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik int accessLevel = Calendars.CAL_ACCESS_NONE; 4448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Get the calendar id for this event 4450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Cursor cursor = cr.query(ContentUris.withAppendedId(Events.CONTENT_URI, e.id), 4451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project new String[] { Events.CALENDAR_ID }, 4452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* selection */, 4453146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* selectionArgs */, 4454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project null /* sort */); 4455e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4456e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan if (cursor == null) { 4457a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 4458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4459e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4460e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan if (cursor.getCount() == 0) { 4461e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan cursor.close(); 4462a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 4463e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan } 4464e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.moveToFirst(); 4466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project long calId = cursor.getLong(0); 4467697bd6a8cec36cc75c72603674e57e4c6fe42dbfKen Shirriff cursor.close(); 4468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Uri uri = Calendars.CONTENT_URI; 4470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project String where = String.format(CALENDARS_WHERE, calId); 4471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor = cr.query(uri, CALENDARS_PROJECTION, where, null, null); 4472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 44736d34cec523930368976bc8d358d0a6de1da3462cMichael Chan String calendarOwnerAccount = null; 4474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (cursor != null) { 4475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.moveToFirst(); 4476ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan accessLevel = cursor.getInt(CALENDARS_INDEX_ACCESS_LEVEL); 44776d34cec523930368976bc8d358d0a6de1da3462cMichael Chan calendarOwnerAccount = cursor.getString(CALENDARS_INDEX_OWNER_ACCOUNT); 4478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cursor.close(); 4479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4480e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4481ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik if (accessLevel < Calendars.CAL_ACCESS_CONTRIBUTOR) { 4482a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_NONE; 44836d34cec523930368976bc8d358d0a6de1da3462cMichael Chan } 4484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 44856d34cec523930368976bc8d358d0a6de1da3462cMichael Chan if (e.guestsCanModify) { 4486a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_EDIT; 4487a505627659f6bfba8869eac8089f7030f2d0d92cErik } 4488a505627659f6bfba8869eac8089f7030f2d0d92cErik 448946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (!TextUtils.isEmpty(calendarOwnerAccount) 449046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan && calendarOwnerAccount.equalsIgnoreCase(e.organizer)) { 4491a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_EDIT; 4492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4494a505627659f6bfba8869eac8089f7030f2d0d92cErik return ACCESS_LEVEL_DELETE; 4495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 4498146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Sets mSelectionDay and mSelectionHour based on the (x,y) touch position. 4499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * If the touch position is not within the displayed grid, then this 4500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * method returns false. 4501146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * 4502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param x the x position of the touch 4503146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @param y the y position of the touch 4504989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson * @param keepOldSelection - do not change the selection info (used for invoking accessibility 4505989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson * messages) 4506146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * @return true if the touch position is valid 4507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 4508989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson private boolean setSelectionFromPosition(int x, final int y, boolean keepOldSelection) { 4509989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson 4510989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson Event savedEvent = null; 4511989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson int savedDay = 0; 4512989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson int savedHour = 0; 4513989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson boolean savedAllDay = false; 4514989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson if (keepOldSelection) { 4515989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson // Store selection info and restore it at the end. This way, we can invoke the 4516989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson // right accessibility message without affecting the selection. 4517989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson savedEvent = mSelectedEvent; 4518989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson savedDay = mSelectionDay; 4519989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson savedHour = mSelectionHour; 4520989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson savedAllDay = mSelectionAllday; 4521989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson } 4522146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (x < mHoursWidth) { 4523360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan x = mHoursWidth; 4524146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int day = (x - mHoursWidth) / (mCellWidth + DAY_GAP); 4527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (day >= mNumDays) { 4528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project day = mNumDays - 1; 4529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project day += mFirstJulianDay; 4531989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedDay(day); 4532360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan 4533360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan if (y < DAY_HEADER_HEIGHT) { 4534aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan sendAccessibilityEventAsNeeded(false); 4535360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan return false; 4536360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan } 453746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 4538989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(mFirstHour); /* First fully visible hour */ 453946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 454046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan if (y < mFirstCell) { 45412fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = true; 4542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 454346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // y is now offset from top of the scrollable region 454455a26d7062d5aa1a1b001b7271bb137276ab807eErik int adjustedY = y - mFirstCell; 454546a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 454655a26d7062d5aa1a1b001b7271bb137276ab807eErik if (adjustedY < mFirstHourOffset) { 4547989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(mSelectionHour - 1); /* In the partially visible hour */ 454846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } else { 4549989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(mSelectionHour + 4550989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson (adjustedY - mFirstHourOffset) / (mCellHeight + HOUR_GAP)); 455146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan } 455246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 45532fda24534978f55711526dbde747aa50d68dec40RoboErik mSelectionAllday = false; 4554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4555360c67c9227c3e75cb4ea9b7350e3ed44b504f03Michael Chan 4556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project findSelectedEvent(x, y); 455746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 455846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// Log.i("Cal", "setSelectionFromPosition( " + x + ", " + y + " ) day: " + day + " hour: " 455946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// + mSelectionHour + " mFirstCell: " + mFirstCell + " mFirstHourOffset: " 456046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// + mFirstHourOffset); 4561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// if (mSelectedEvent != null) { 456246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// Log.i("Cal", " num events: " + mSelectedEvents.size() + " event: " 456346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// + mSelectedEvent.title); 4564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// for (Event ev : mSelectedEvents) { 4565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL 4566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// | DateUtils.FORMAT_CAP_NOON_MIDNIGHT; 456746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan// String timeRange = formatDateRange(mContext, ev.startMillis, ev.endMillis, flags); 4568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// 4569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// Log.i("Cal", " " + timeRange + " " + ev.title); 4570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// } 4571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// } 4572aeae98bf8f8c5c544f65f5b6b7f29cfd31366ad5Michael Chan sendAccessibilityEventAsNeeded(true); 4573989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson 4574989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson // Restore old values 4575989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson if (keepOldSelection) { 4576989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mSelectedEvent = savedEvent; 4577989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mSelectionDay = savedDay; 4578989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mSelectionHour = savedHour; 4579989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mSelectionAllday = savedAllDay; 4580989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson } 4581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return true; 4582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private void findSelectedEvent(int x, int y) { 4585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int date = mSelectionDay; 4586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int cellWidth = mCellWidth; 4587b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik ArrayList<Event> events = mEvents; 4588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int numEvents = events.size(); 4589e9cd8f4513c141ca486bbd141f0fe34bb3c27f3aRoboErik int left = computeDayLeftPosition(mSelectionDay - mFirstJulianDay); 4590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int top = 0; 4591989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(null); 4592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.clear(); 45942fda24534978f55711526dbde747aa50d68dec40RoboErik if (mSelectionAllday) { 4595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float yDistance; 459646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan float minYdistance = 10000.0f; // any large number 4597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event closestEvent = null; 45982fda24534978f55711526dbde747aa50d68dec40RoboErik float drawHeight = mAlldayHeight; 45993eea5ad7329f522d9fe091ca51ad09b809bba34bMichael Chan int yOffset = DAY_HEADER_HEIGHT + ALLDAY_TOP_MARGIN; 46002fda24534978f55711526dbde747aa50d68dec40RoboErik int maxUnexpandedColumn = mMaxUnexpandedAlldayEventCount; 46012fda24534978f55711526dbde747aa50d68dec40RoboErik if (mMaxAlldayEvents > mMaxUnexpandedAlldayEventCount) { 46022fda24534978f55711526dbde747aa50d68dec40RoboErik // Leave a gap for the 'box +n' text 46032fda24534978f55711526dbde747aa50d68dec40RoboErik maxUnexpandedColumn--; 46042fda24534978f55711526dbde747aa50d68dec40RoboErik } 4605b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik events = mAllDayEvents; 4606b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik numEvents = events.size(); 4607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 4608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 46092fda24534978f55711526dbde747aa50d68dec40RoboErik if (!event.drawAsAllday() || 46102fda24534978f55711526dbde747aa50d68dec40RoboErik (!mShowAllAllDayEvents && event.getColumn() >= maxUnexpandedColumn)) { 46112fda24534978f55711526dbde747aa50d68dec40RoboErik // Don't check non-allday events or events that aren't shown 4612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 4613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (event.startDay <= mSelectionDay && event.endDay >= mSelectionDay) { 4616b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik float numRectangles = mShowAllAllDayEvents ? mMaxAlldayEvents 4617b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik : mMaxUnexpandedAlldayEventCount; 4618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float height = drawHeight / numRectangles; 4619f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan if (height > MAX_HEIGHT_OF_ONE_ALLDAY_EVENT) { 4620f056fac66fe2845bfd88e9571f8fceb9180264a0Michael Chan height = MAX_HEIGHT_OF_ONE_ALLDAY_EVENT; 4621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float eventTop = yOffset + height * event.getColumn(); 4623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float eventBottom = eventTop + height; 4624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (eventTop < y && eventBottom > y) { 4625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the touch is inside the event rectangle, then 4626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // add the event. 4627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 4628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = event; 4629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project break; 4630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Find the closest event 4632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (eventTop >= y) { 4633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project yDistance = eventTop - y; 4634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project yDistance = y - eventBottom; 4636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (yDistance < minYdistance) { 4638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project minYdistance = yDistance; 4639146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = event; 4640146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4641146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4643146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4644989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(closestEvent); 4645146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project return; 4646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4647146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4648146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Adjust y for the scrollable bitmap 4649146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project y += mViewStartY - mFirstCell; 4650146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Use a region around (x,y) for the selection region 4652146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Rect region = mRect; 4653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.left = x - 10; 4654146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.right = x + 10; 4655146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.top = y - 10; 4656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project region.bottom = y + 10; 4657146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4658146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project EventGeometry geometry = mEventGeometry; 4659146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4660146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int i = 0; i < numEvents; i++) { 4661146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event event = events.get(i); 4662146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Compute the event rectangle. 4663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (!geometry.computeEventRect(date, left, top, cellWidth, event)) { 4664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project continue; 4665146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If the event intersects the selection region, then add it to 4668146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // mSelectedEvents. 4669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (geometry.eventIntersectsSelection(event, region)) { 4670146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mSelectedEvents.add(event); 4671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4672146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4674146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // If there are any events in the selected region, then assign the 4675146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // closest one to mSelectedEvent. 4676146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvents.size() > 0) { 4677146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int len = mSelectedEvents.size(); 4678146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event closestEvent = null; 467946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan float minDist = mViewWidth + mViewHeight; // some large distance 4680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project for (int index = 0; index < len; index++) { 4681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project Event ev = mSelectedEvents.get(index); 4682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project float dist = geometry.pointToEvent(x, y, ev); 4683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (dist < minDist) { 4684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project minDist = dist; 4685146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project closestEvent = ev; 4686146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4687146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4688989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedEvent(closestEvent); 4689146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4690146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Keep the selected hour and day consistent with the selected 469146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // event. They could be different if we touched on an empty hour 469246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // slot very close to an event in the previous hour slot. In 4693146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // that case we will select the nearby event. 4694146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startDay = mSelectedEvent.startDay; 4695146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endDay = mSelectedEvent.endDay; 4696146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectionDay < startDay) { 4697989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedDay(startDay); 4698146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else if (mSelectionDay > endDay) { 4699989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedDay(endDay); 4700146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4701146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4702146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int startHour = mSelectedEvent.startTime / 60; 4703146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project int endHour; 4704146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mSelectedEvent.startTime < mSelectedEvent.endTime) { 4705146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endHour = (mSelectedEvent.endTime - 1) / 60; 4706146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } else { 4707146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project endHour = mSelectedEvent.endTime / 60; 4708146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4709146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4710349dd91e8475a72eb68a5eae4482ce7e82c01d16RoboErik if (mSelectionHour < startHour && mSelectionDay == startDay) { 4711989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(startHour); 4712349dd91e8475a72eb68a5eae4482ce7e82c01d16RoboErik } else if (mSelectionHour > endHour && mSelectionDay == endDay) { 4713989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson setSelectedHour(endHour); 4714146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4715146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4716146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4717146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4718146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Encapsulates the code to continue the scrolling after the 471946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan // finger is lifted. Instead of stopping the scroll immediately, 4720146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // the scroll continues to "free spin" and gradually slows down. 4721146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project private class ContinueScroll implements Runnable { 4722146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 47233f6328f579b05c02606572c777541b97aa04f9f3Michael Chan mScrolling = mScrolling && mScroller.computeScrollOffset(); 4724ea3f117db073ae796453479d00e9c7664d4471c5RoboErik if (!mScrolling || mPaused) { 47253f6328f579b05c02606572c777541b97aa04f9f3Michael Chan resetSelectedHour(); 47263f6328f579b05c02606572c777541b97aa04f9f3Michael Chan invalidate(); 47273f6328f579b05c02606572c777541b97aa04f9f3Michael Chan return; 4728146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4729146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 47303f6328f579b05c02606572c777541b97aa04f9f3Michael Chan mViewStartY = mScroller.getCurrY(); 4731146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4732433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mCallEdgeEffectOnAbsorb) { 4733433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mViewStartY < 0) { 4734433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectTop.onAbsorb((int) mLastVelocity); 4735433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mCallEdgeEffectOnAbsorb = false; 4736433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } else if (mViewStartY > mMaxViewStartY) { 4737433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mEdgeEffectBottom.onAbsorb((int) mLastVelocity); 4738433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mCallEdgeEffectOnAbsorb = false; 4739433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4740433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mLastVelocity = mScroller.getCurrVelocity(); 4741433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4742433ba924de1ac26b923e2beb061812012749e4f3Michael Chan 4743433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mScrollStartY == 0 || mScrollStartY == mMaxViewStartY) { 4744433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // Allow overscroll/springback only on a fling, 4745433ba924de1ac26b923e2beb061812012749e4f3Michael Chan // not a pull/fling from the end 4746433ba924de1ac26b923e2beb061812012749e4f3Michael Chan if (mViewStartY < 0) { 4747433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mViewStartY = 0; 4748433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } else if (mViewStartY > mMaxViewStartY) { 4749433ba924de1ac26b923e2beb061812012749e4f3Michael Chan mViewStartY = mMaxViewStartY; 4750433ba924de1ac26b923e2beb061812012749e4f3Michael Chan } 4751146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4752146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4753146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project computeFirstHour(); 4754ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.post(this); 4755146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project invalidate(); 4756146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4757146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4758146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4759146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project /** 4760bd0e834aea317236d574f8738fe11a51fdc87968Erik * Cleanup the pop-up and timers. 4761146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */ 4762146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void cleanup() { 4763146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against null-pointer exceptions 4764146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPopup != null) { 4765146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 4766146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4767ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mPaused = true; 4768666fc5e8ddbac15c951aad738bd818ee307eae42Erik mLastPopupEventID = INVALID_EVENT_ID; 476958f5055e1f3740382b4507e6eb88eebc2d6c21c1Michael Chan if (mHandler != null) { 477058f5055e1f3740382b4507e6eb88eebc2d6c21c1Michael Chan mHandler.removeCallbacks(mDismissPopup); 477158f5055e1f3740382b4507e6eb88eebc2d6c21c1Michael Chan mHandler.removeCallbacks(mUpdateCurrentTime); 4772146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4773e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan 4774d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan Utils.setSharedPreference(mContext, GeneralPreferences.KEY_DEFAULT_CELL_HEIGHT, 4775d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan mCellHeight); 4776056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // Clear all click animations 4777ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson eventClickCleanup(); 47787abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project // Turn off redraw 47797abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project mRemeasure = false; 478084fbd42c4ea8bae2a0edbd49333cb7112bf3cd51Isaac Katzenelson // Turn off scrolling to make sure the view is in the correct state if we fling back to it 478184fbd42c4ea8bae2a0edbd49333cb7112bf3cd51Isaac Katzenelson mScrolling = false; 4782146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4783146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4784ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson private void eventClickCleanup() { 4785ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson this.removeCallbacks(mClearClick); 4786ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson this.removeCallbacks(mSetClick); 4787ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson mClickedEvent = null; 4788ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson mSavedClickedEvent = null; 4789ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson } 4790ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson 4791989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson private void setSelectedEvent(Event e) { 4792989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mSelectedEvent = e; 4793989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mSelectedEventForAccessibility = e; 4794989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson } 4795989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson 4796989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson private void setSelectedHour(int h) { 4797989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mSelectionHour = h; 4798989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mSelectionHourForAccessibility = h; 4799989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson } 4800989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson private void setSelectedDay(int d) { 4801989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mSelectionDay = d; 4802989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson mSelectionDayForAccessibility = d; 4803989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson } 4804989a7fe5215b378bb6dac7eae7d9970056e30c4fIsaac Katzenelson 4805bd0e834aea317236d574f8738fe11a51fdc87968Erik /** 4806bd0e834aea317236d574f8738fe11a51fdc87968Erik * Restart the update timer 4807bd0e834aea317236d574f8738fe11a51fdc87968Erik */ 4808bd0e834aea317236d574f8738fe11a51fdc87968Erik public void restartCurrentTimeUpdates() { 4809ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mPaused = false; 4810ea3f117db073ae796453479d00e9c7664d4471c5RoboErik if (mHandler != null) { 48115d740e1320ba48ba66b72430f9896ab7d481fb54Michael Chan mHandler.removeCallbacks(mUpdateCurrentTime); 4812ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.post(mUpdateCurrentTime); 4813ea3f117db073ae796453479d00e9c7664d4471c5RoboErik } 4814bd0e834aea317236d574f8738fe11a51fdc87968Erik } 4815bd0e834aea317236d574f8738fe11a51fdc87968Erik 481646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan @Override 481746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan protected void onDetachedFromWindow() { 4818146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project cleanup(); 4819146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project super.onDetachedFromWindow(); 4820146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4821146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project 4822146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project class DismissPopup implements Runnable { 4823146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project public void run() { 4824146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project // Protect against null-pointer exceptions 4825146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project if (mPopup != null) { 4826146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project mPopup.dismiss(); 4827146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4828146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4829146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project } 4830bd0e834aea317236d574f8738fe11a51fdc87968Erik 4831bd0e834aea317236d574f8738fe11a51fdc87968Erik class UpdateCurrentTime implements Runnable { 4832bd0e834aea317236d574f8738fe11a51fdc87968Erik public void run() { 4833bd0e834aea317236d574f8738fe11a51fdc87968Erik long currentTime = System.currentTimeMillis(); 4834bd0e834aea317236d574f8738fe11a51fdc87968Erik mCurrentTime.set(currentTime); 4835bd0e834aea317236d574f8738fe11a51fdc87968Erik //% causes update to occur on 5 minute marks (11:10, 11:15, 11:20, etc.) 48365d740e1320ba48ba66b72430f9896ab7d481fb54Michael Chan if (!DayView.this.mPaused) { 4837ea3f117db073ae796453479d00e9c7664d4471c5RoboErik mHandler.postDelayed(mUpdateCurrentTime, UPDATE_CURRENT_TIME_DELAY 4838ea3f117db073ae796453479d00e9c7664d4471c5RoboErik - (currentTime % UPDATE_CURRENT_TIME_DELAY)); 48395d740e1320ba48ba66b72430f9896ab7d481fb54Michael Chan } 4840bd0e834aea317236d574f8738fe11a51fdc87968Erik mTodayJulianDay = Time.getJulianDay(currentTime, mCurrentTime.gmtoff); 4841bd0e834aea317236d574f8738fe11a51fdc87968Erik invalidate(); 4842bd0e834aea317236d574f8738fe11a51fdc87968Erik } 4843bd0e834aea317236d574f8738fe11a51fdc87968Erik } 4844ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 4845ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener { 4846ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 4847ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onSingleTapUp(MotionEvent ev) { 48489ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "GestureDetector.onSingleTapUp"); 4849d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doSingleTapUp(ev); 4850ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 4851ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4852ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 4853ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 4854ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public void onLongPress(MotionEvent ev) { 48559ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "GestureDetector.onLongPress"); 4856d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doLongPress(ev); 4857ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4858ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 4859ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 4860ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 48619ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "GestureDetector.onScroll"); 4862ca0955e1dbd3176cde0d012552efdca7b5e336d6Isaac Katzenelson eventClickCleanup(); 48632fda24534978f55711526dbde747aa50d68dec40RoboErik if (mTouchStartedInAlldayArea) { 48640e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik if (Math.abs(distanceX) < Math.abs(distanceY)) { 4865056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // Make sure that click feedback is gone when you scroll from the 4866056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson // all day area 4867056c51ec65d03c19348fb64b65a00835e5ecd600Isaac Katzenelson invalidate(); 48680e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik return false; 48690e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik } 48700e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik // don't scroll vertically if this started in the allday area 48710e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik distanceY = 0; 48722fda24534978f55711526dbde747aa50d68dec40RoboErik } 4873d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doScroll(e1, e2, distanceX, distanceY); 4874ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 4875ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4876ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 4877ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 4878ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 48799ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "GestureDetector.onFling"); 48809ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan 48812fda24534978f55711526dbde747aa50d68dec40RoboErik if (mTouchStartedInAlldayArea) { 48820e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik if (Math.abs(velocityX) < Math.abs(velocityY)) { 48830e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik return false; 48840e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik } 48850e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik // don't fling vertically if this started in the allday area 48860e9e8a522740e4083f944638a82d5bd7a6e89fa8Erik velocityY = 0; 48872fda24534978f55711526dbde747aa50d68dec40RoboErik } 4888d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doFling(e1, e2, velocityX, velocityY); 4889ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 4890ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4891ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan 4892ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan @Override 4893ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan public boolean onDown(MotionEvent ev) { 48949ddc5e29f501e423e873c4a1d4cfb7e810d63ccfMichael Chan if (DEBUG) Log.e(TAG, "GestureDetector.onDown"); 4895d190418220467c02327dd9b3ae1eae238889720bMichael Chan DayView.this.doDown(ev); 4896ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan return true; 4897ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4898ef1a51d6dda6dd8a013bf0937f10c6eb2041b888Michael Chan } 4899cd405a28e6821b116dcf3c531805d0c90b6cc08cErik 4900cd405a28e6821b116dcf3c531805d0c90b6cc08cErik @Override 4901cd405a28e6821b116dcf3c531805d0c90b6cc08cErik public boolean onLongClick(View v) { 490243e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik int flags = DateUtils.FORMAT_SHOW_WEEKDAY; 490343e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik long time = getSelectedTimeInMillis(); 490443e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik if (!mSelectionAllday) { 490543e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik flags |= DateUtils.FORMAT_SHOW_TIME; 490643e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik } 490743e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik if (DateFormat.is24HourFormat(mContext)) { 490843e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik flags |= DateUtils.FORMAT_24HOUR; 490943e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik } 491043e794f69384bf8fd2370e71aceb1fb58d6cf958RoboErik mLongPressTitle = Utils.formatDateRange(mContext, time, time, flags); 491120b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik new AlertDialog.Builder(mContext).setTitle(mLongPressTitle) 491220b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik .setItems(mLongPressItems, new DialogInterface.OnClickListener() { 491320b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik @Override 491420b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik public void onClick(DialogInterface dialog, int which) { 491520b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik if (which == 0) { 4916edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan long extraLong = 0; 4917edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan if (mSelectionAllday) { 4918edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan extraLong = CalendarController.EXTRA_CREATE_ALL_DAY; 4919edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan } 4920edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan mController.sendEventRelatedEventWithExtra(this, 4921edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan EventType.CREATE_EVENT, -1, getSelectedTimeInMillis(), 0, -1, 4922edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan -1, extraLong, -1); 492320b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik } 492420b6fb580bf09dbd610a256ffd3165c03053cb70RoboErik } 492573bb3ae73b067e7c926d3ac660d059b2a06309b2RoboErik }).show().setCanceledOnTouchOutside(true); 4926cd405a28e6821b116dcf3c531805d0c90b6cc08cErik return true; 4927cd405a28e6821b116dcf3c531805d0c90b6cc08cErik } 49282c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 49292c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan // The rest of this file was borrowed from Launcher2 - PagedView.java 49302c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan private static final int MINIMUM_SNAP_VELOCITY = 2200; 49312c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 493295d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan private class ScrollInterpolator implements Interpolator { 49332c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan public ScrollInterpolator() { 49342c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 49352c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 49362c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan public float getInterpolation(float t) { 49372c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan t -= 1.0f; 493895d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan t = t * t * t * t * t + 1; 493995d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan 494095d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan if ((1 - t) * mAnimationDistance < 1) { 494195d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan cancelAnimation(); 494295d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan } 494395d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan 494495d9f9172802f19e28b1cabf39b371c4ac343dc2Michael Chan return t; 49452c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 49462c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 49472c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 49482c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan private long calculateDuration(float delta, float width, float velocity) { 49492c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan /* 49502c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * Here we compute a "distance" that will be used in the computation of 49512c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * the overall snap duration. This is a function of the actual distance 49522c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * that needs to be traveled; we keep this value close to half screen 49532c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * size in order to reduce the variance in snap duration as a function 49542c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * of the distance the page needs to travel. 49552c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan */ 49562c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan final float halfScreenSize = width / 2; 49572c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan float distanceRatio = delta / width; 49582c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan float distanceInfluenceForSnapDuration = distanceInfluenceForSnapDuration(distanceRatio); 49592c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan float distance = halfScreenSize + halfScreenSize * distanceInfluenceForSnapDuration; 49602c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 49612c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan velocity = Math.abs(velocity); 49622c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan velocity = Math.max(MINIMUM_SNAP_VELOCITY, velocity); 49632c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 49642c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan /* 49652c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * we want the page's snap velocity to approximately match the velocity 49662c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * at which the user flings, so we scale the duration by a value near to 49672c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * the derivative of the scroll interpolator at zero, ie. 5. We use 6 to 49682c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * make it a little slower. 49692c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan */ 49702c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan long duration = 6 * Math.round(1000 * Math.abs(distance / velocity)); 49712c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan if (DEBUG) { 49722c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan Log.e(TAG, "halfScreenSize:" + halfScreenSize + " delta:" + delta + " distanceRatio:" 49732c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan + distanceRatio + " distance:" + distance + " velocity:" + velocity 49742c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan + " duration:" + duration + " distanceInfluenceForSnapDuration:" 49752c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan + distanceInfluenceForSnapDuration); 49762c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 49772c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan return duration; 49782c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 49792c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan 49802c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan /* 49812c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * We want the duration of the page snap animation to be influenced by the 49822c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * distance that the screen has to travel, however, we don't want this 49832c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * duration to be effected in a purely linear fashion. Instead, we use this 49842c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * method to moderate the effect that the distance of travel has on the 49852c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan * overall snap duration. 49862c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan */ 49872c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan private float distanceInfluenceForSnapDuration(float f) { 49882c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan f -= 0.5f; // center the values about 0. 49892c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan f *= 0.3f * Math.PI / 2.0f; 49902c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan return (float) Math.sin(f); 49912c0a3ca970425b0237cd9d99b943a9cd17529692Michael Chan } 4992146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project} 4993