14970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan/* 24970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * Copyright (C) 2010 The Android Open Source Project 34970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * 44970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * Licensed under the Apache License, Version 2.0 (the "License"); 54970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * you may not use this file except in compliance with the License. 64970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * You may obtain a copy of the License at 74970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * 84970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * http://www.apache.org/licenses/LICENSE-2.0 94970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * 104970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * Unless required by applicable law or agreed to in writing, software 114970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * distributed under the License is distributed on an "AS IS" BASIS, 124970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * See the License for the specific language governing permissions and 144970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan * limitations under the License. 154970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan */ 164970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan 174970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chanpackage com.android.calendar; 184970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan 19a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport static android.provider.CalendarContract.EXTRA_EVENT_BEGIN_TIME; 20a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport static android.provider.CalendarContract.EXTRA_EVENT_END_TIME; 21edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chanimport static android.provider.CalendarContract.EXTRA_EVENT_ALL_DAY; 226bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelsonimport static android.provider.CalendarContract.Attendees.ATTENDEE_STATUS; 239e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan 245f62079ab9daefe95ede87631766e99e8b4a2220Erikimport com.android.calendar.event.EditEventActivity; 252aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport com.android.calendar.selectcalendars.SelectVisibleCalendarsActivity; 265f62079ab9daefe95ede87631766e99e8b4a2220Erik 27ba1b94afd187279623a57417da1ef78efa1217e2Erikimport android.accounts.Account; 287dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFaddenimport android.accounts.AccountManager; 2983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chanimport android.app.Activity; 306d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawaimport android.app.SearchManager; 316d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawaimport android.app.SearchableInfo; 326d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawaimport android.content.ComponentName; 33ba1b94afd187279623a57417da1ef78efa1217e2Erikimport android.content.ContentResolver; 349e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chanimport android.content.ContentUris; 35ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chanimport android.content.Context; 369e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chanimport android.content.Intent; 37ba1b94afd187279623a57417da1ef78efa1217e2Erikimport android.database.Cursor; 389e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chanimport android.net.Uri; 397116ba44f2aa65a126bc6f0b600bc91bd9d8f170Erikimport android.os.AsyncTask; 40ba1b94afd187279623a57417da1ef78efa1217e2Erikimport android.os.Bundle; 416bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelsonimport android.provider.CalendarContract.Attendees; 42a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Calendars; 43a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Events; 44ba1b94afd187279623a57417da1ef78efa1217e2Erikimport android.text.TextUtils; 454970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chanimport android.text.format.Time; 4683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chanimport android.util.Log; 473864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErikimport android.util.Pair; 4883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 493f348f3ea8a7927566a1283b6d6bb5e220662889Erikimport java.util.Iterator; 503f348f3ea8a7927566a1283b6d6bb5e220662889Erikimport java.util.LinkedHashMap; 51ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chanimport java.util.LinkedList; 523f348f3ea8a7927566a1283b6d6bb5e220662889Erikimport java.util.Map.Entry; 5383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chanimport java.util.WeakHashMap; 5483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 5525251192d80159d4cf0934f3ac5c84cb0b8b7365Erikpublic class CalendarController { 56f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan private static final boolean DEBUG = false; 5783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan private static final String TAG = "CalendarController"; 58ba1b94afd187279623a57417da1ef78efa1217e2Erik private static final String REFRESH_SELECTION = Calendars.SYNC_EVENTS + "=?"; 59ba1b94afd187279623a57417da1ef78efa1217e2Erik private static final String[] REFRESH_ARGS = new String[] { "1" }; 600e1e62408b96e1532eb6f6a609ae4c817751aaf3RoboErik private static final String REFRESH_ORDER = Calendars.ACCOUNT_NAME + "," 610e1e62408b96e1532eb6f6a609ae4c817751aaf3RoboErik + Calendars.ACCOUNT_TYPE; 6283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 63a7694eead7cbb293990bc89c3906e17bad36194cErik public static final String EVENT_EDIT_ON_LAUNCH = "editMode"; 64a7694eead7cbb293990bc89c3906e17bad36194cErik 65981874e61ecf29a96a77601a3172b2503b6537eeErik public static final int MIN_CALENDAR_YEAR = 1970; 66981874e61ecf29a96a77601a3172b2503b6537eeErik public static final int MAX_CALENDAR_YEAR = 2036; 67981874e61ecf29a96a77601a3172b2503b6537eeErik public static final int MIN_CALENDAR_WEEK = 0; 68981874e61ecf29a96a77601a3172b2503b6537eeErik public static final int MAX_CALENDAR_WEEK = 3497; // weeks between 1/1/1970 and 1/1/2037 69981874e61ecf29a96a77601a3172b2503b6537eeErik 706bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private final Context mContext; 71ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan 723f348f3ea8a7927566a1283b6d6bb5e220662889Erik // This uses a LinkedHashMap so that we can replace fragments based on the 733f348f3ea8a7927566a1283b6d6bb5e220662889Erik // view id they are being expanded into since we can't guarantee a reference 743f348f3ea8a7927566a1283b6d6bb5e220662889Erik // to the handler will be findable 756bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private final LinkedHashMap<Integer,EventHandler> eventHandlers = 763f348f3ea8a7927566a1283b6d6bb5e220662889Erik new LinkedHashMap<Integer,EventHandler>(5); 776bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private final LinkedList<Integer> mToBeRemovedEventHandlers = new LinkedList<Integer>(); 786bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private final LinkedHashMap<Integer, EventHandler> mToBeAddedEventHandlers = new LinkedHashMap< 79cb81189e4868769ea016253eca104e46df2f033aErik Integer, EventHandler>(); 803864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik private Pair<Integer, EventHandler> mFirstEventHandler; 813864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik private Pair<Integer, EventHandler> mToBeAddedFirstEventHandler; 82ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson private volatile int mDispatchInProgressCounter = 0; 8383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 840558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan private static WeakHashMap<Context, CalendarController> instances = 850558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan new WeakHashMap<Context, CalendarController>(); 860558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan 876bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private final WeakHashMap<Object, Long> filters = new WeakHashMap<Object, Long>(1); 884970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan 893458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan private int mViewType = -1; 9085e550966b125220af5faa7407a0cfc0b54494aaMichael Chan private int mDetailViewType = -1; 91ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan private int mPreviousViewType = -1; 927b92da258a480284dcc15a518ea570072329a31dErik private long mEventId = -1; 936bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private final Time mTime = new Time(); 94c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik private long mDateFlags = 0; 953458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan 966bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private final Runnable mUpdateTimezone = new Runnable() { 974679f6009e8d754e4d76c68a0c5a0a32b23f7f0cRoboErik @Override 984679f6009e8d754e4d76c68a0c5a0a32b23f7f0cRoboErik public void run() { 994679f6009e8d754e4d76c68a0c5a0a32b23f7f0cRoboErik mTime.switchTimezone(Utils.getTimeZone(mContext, this)); 1004679f6009e8d754e4d76c68a0c5a0a32b23f7f0cRoboErik } 1014679f6009e8d754e4d76c68a0c5a0a32b23f7f0cRoboErik }; 1024679f6009e8d754e4d76c68a0c5a0a32b23f7f0cRoboErik 1034970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan /** 10483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * One of the event types that are sent to or from the controller 1054970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan */ 10625251192d80159d4cf0934f3ac5c84cb0b8b7365Erik public interface EventType { 1079e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan final long CREATE_EVENT = 1L; 108deced8999da73effe4133e2317c262fea7910090Michael Chan 109deced8999da73effe4133e2317c262fea7910090Michael Chan // Simple view of an event 11083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan final long VIEW_EVENT = 1L << 1; 111deced8999da73effe4133e2317c262fea7910090Michael Chan 112deced8999da73effe4133e2317c262fea7910090Michael Chan // Full detail view in read only mode 113deced8999da73effe4133e2317c262fea7910090Michael Chan final long VIEW_EVENT_DETAILS = 1L << 2; 114deced8999da73effe4133e2317c262fea7910090Michael Chan 115a7694eead7cbb293990bc89c3906e17bad36194cErik // full detail view in edit mode 116deced8999da73effe4133e2317c262fea7910090Michael Chan final long EDIT_EVENT = 1L << 3; 117deced8999da73effe4133e2317c262fea7910090Michael Chan 118deced8999da73effe4133e2317c262fea7910090Michael Chan final long DELETE_EVENT = 1L << 4; 11983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 120deced8999da73effe4133e2317c262fea7910090Michael Chan final long GO_TO = 1L << 5; 12183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 122deced8999da73effe4133e2317c262fea7910090Michael Chan final long LAUNCH_SETTINGS = 1L << 6; 123954c871f4753d3182314d7027c0dd17c236d9ca7Erik 124deced8999da73effe4133e2317c262fea7910090Michael Chan final long EVENTS_CHANGED = 1L << 7; 1254003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang 126deced8999da73effe4133e2317c262fea7910090Michael Chan final long SEARCH = 1L << 8; 1277b92da258a480284dcc15a518ea570072329a31dErik 1287b92da258a480284dcc15a518ea570072329a31dErik // User has pressed the home key 129deced8999da73effe4133e2317c262fea7910090Michael Chan final long USER_HOME = 1L << 9; 130eaafa2b48be7194a61754604ae37b3d62e9118d8Erik 131eaafa2b48be7194a61754604ae37b3d62e9118d8Erik // date range has changed, update the title 132eaafa2b48be7194a61754604ae37b3d62e9118d8Erik final long UPDATE_TITLE = 1L << 10; 1332aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1342aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // select which calendars to display 1352aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan final long LAUNCH_SELECT_VISIBLE_CALENDARS = 1L << 11; 13683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 1374970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan 1384970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan /** 13983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * One of the Agenda/Day/Week/Month view types 1404970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan */ 14125251192d80159d4cf0934f3ac5c84cb0b8b7365Erik public interface ViewType { 142d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan final int DETAIL = -1; 1433458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan final int CURRENT = 0; 1443458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan final int AGENDA = 1; 1453458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan final int DAY = 2; 1463458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan final int WEEK = 3; 1473458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan final int MONTH = 4; 148dd95df57c8c5a58a85c4c0effad5652dec14f621Erik final int EDIT = 5; 14983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 15083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 15125251192d80159d4cf0934f3ac5c84cb0b8b7365Erik public static class EventInfo { 1526bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson 1536bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private static final long ATTENTEE_STATUS_MASK = 0xFF; 1546bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private static final long ALL_DAY_MASK = 0x100; 1556bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private static final int ATTENDEE_STATUS_NONE_MASK = 0x01; 1566bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private static final int ATTENDEE_STATUS_ACCEPTED_MASK = 0x02; 1576bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private static final int ATTENDEE_STATUS_DECLINED_MASK = 0x04; 1586bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson private static final int ATTENDEE_STATUS_TENTATIVE_MASK = 0x08; 1596bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson 16000b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang public long eventType; // one of the EventType 16100b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang public int viewType; // one of the ViewType 16200b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang public long id; // event id 16300b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang public Time selectedTime; // the selected time in focus 16400b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang public Time startTime; // start of a range of time. 16500b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang public Time endTime; // end of a range of time. 16600b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang public int x; // x coordinate in the activity space 16700b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang public int y; // y coordinate in the activity space 16800b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang public String query; // query for a user search 1696d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa public ComponentName componentName; // used in combination with query 17046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 17146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** 17246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * For EventType.VIEW_EVENT: 1736bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson * It is the default attendee response and an all day event indicator. 1746bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson * Set to Attendees.ATTENDEE_STATUS_NONE, Attendees.ATTENDEE_STATUS_ACCEPTED, 1756bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson * Attendees.ATTENDEE_STATUS_DECLINED, or Attendees.ATTENDEE_STATUS_TENTATIVE. 1766bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson * To signal the event is an all-day event, "or" ALL_DAY_MASK with the response. 1776bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson * Alternatively, use buildViewExtraLong(), getResponse(), and isAllDay(). 17846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * <p> 179edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan * For EventType.CREATE_EVENT: 180edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan * Set to {@link #EXTRA_CREATE_ALL_DAY} for creating an all-day event. 181edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan * <p> 18246a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * For EventType.GO_TO: 18346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * Set to {@link #EXTRA_GOTO_TIME} to go to the specified date/time. 18446a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * Set to {@link #EXTRA_GOTO_DATE} to consider the date but ignore the time. 185fb0ec227f0d4b3108438c88a6b6d234f5e40fb5cMichael Chan * Set to {@link #EXTRA_GOTO_BACK_TO_PREVIOUS} if back should bring back previous view. 1865b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik * Set to {@link #EXTRA_GOTO_TODAY} if this is a user request to go to the current time. 187fb0ec227f0d4b3108438c88a6b6d234f5e40fb5cMichael Chan * <p> 188fb0ec227f0d4b3108438c88a6b6d234f5e40fb5cMichael Chan * For EventType.UPDATE_TITLE: 189fb0ec227f0d4b3108438c88a6b6d234f5e40fb5cMichael Chan * Set formatting flags for Utils.formatDateRange 19046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan */ 19146a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public long extraLong; 1926bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson 1936bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson public boolean isAllDay() { 1946bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson if (eventType != EventType.VIEW_EVENT) { 1956bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson Log.wtf(TAG, "illegal call to isAllDay , wrong event type " + eventType); 1966bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson return false; 1976bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson } 1986bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson return ((extraLong & ALL_DAY_MASK) != 0) ? true : false; 1996bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson } 2006bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson 2016bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson public int getResponse() { 2026bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson if (eventType != EventType.VIEW_EVENT) { 2036bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson Log.wtf(TAG, "illegal call to getResponse , wrong event type " + eventType); 2046bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson return Attendees.ATTENDEE_STATUS_NONE; 2056bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson } 2066bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson 2076bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson int response = (int)(extraLong & ATTENTEE_STATUS_MASK); 2086bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson switch (response) { 2096bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson case ATTENDEE_STATUS_NONE_MASK: 2106bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson return Attendees.ATTENDEE_STATUS_NONE; 2116bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson case ATTENDEE_STATUS_ACCEPTED_MASK: 2126bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson return Attendees.ATTENDEE_STATUS_ACCEPTED; 2136bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson case ATTENDEE_STATUS_DECLINED_MASK: 2146bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson return Attendees.ATTENDEE_STATUS_DECLINED; 2156bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson case ATTENDEE_STATUS_TENTATIVE_MASK: 2166bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson return Attendees.ATTENDEE_STATUS_TENTATIVE; 2176bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson default: 2186bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson Log.wtf(TAG,"Unknown attendee response " + response); 2196bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson } 2206bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson return ATTENDEE_STATUS_NONE_MASK; 2216bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson } 2226bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson 2236bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson // Used to build the extra long for a VIEW event. 2246bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson public static long buildViewExtraLong(int response, boolean allDay) { 2256bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson long extra = allDay ? ALL_DAY_MASK : 0; 2266bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson 2276bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson switch (response) { 2286bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson case Attendees.ATTENDEE_STATUS_NONE: 2296bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson extra |= ATTENDEE_STATUS_NONE_MASK; 2306bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson break; 2316bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson case Attendees.ATTENDEE_STATUS_ACCEPTED: 2326bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson extra |= ATTENDEE_STATUS_ACCEPTED_MASK; 2336bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson break; 2346bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson case Attendees.ATTENDEE_STATUS_DECLINED: 2356bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson extra |= ATTENDEE_STATUS_DECLINED_MASK; 2366bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson break; 2376bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson case Attendees.ATTENDEE_STATUS_TENTATIVE: 2386bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson extra |= ATTENDEE_STATUS_TENTATIVE_MASK; 2396bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson break; 2406bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson default: 2416bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson Log.wtf(TAG,"Unknown attendee response " + response); 2426bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson extra |= ATTENDEE_STATUS_NONE_MASK; 2436bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson break; 2446bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson } 2456bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson return extra; 2466bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson } 24783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 24883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 24946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan /** 250edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan * Pass to the ExtraLong parameter for EventType.CREATE_EVENT to create 251edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan * an all-day event 252edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan */ 253edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan public static final long EXTRA_CREATE_ALL_DAY = 0x10; 254edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan 255edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan /** 25646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * Pass to the ExtraLong parameter for EventType.GO_TO to signal the time 25746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * can be ignored 25846a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan */ 25946a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan public static final long EXTRA_GOTO_DATE = 1; 260fb0ec227f0d4b3108438c88a6b6d234f5e40fb5cMichael Chan public static final long EXTRA_GOTO_TIME = 2; 261fb0ec227f0d4b3108438c88a6b6d234f5e40fb5cMichael Chan public static final long EXTRA_GOTO_BACK_TO_PREVIOUS = 4; 2625b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public static final long EXTRA_GOTO_TODAY = 8; 26346a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan 26425251192d80159d4cf0934f3ac5c84cb0b8b7365Erik public interface EventHandler { 26583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan long getSupportedEventTypes(); 26683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan void handleEvent(EventInfo event); 26783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 26883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan /** 269954c871f4753d3182314d7027c0dd17c236d9ca7Erik * This notifies the handler that the database has changed and it should 270954c871f4753d3182314d7027c0dd17c236d9ca7Erik * update its view. 27183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan */ 27283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan void eventsChanged(); 27383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 27483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 2750558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan /** 2760558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan * Creates and/or returns an instance of CalendarController associated with 2770558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan * the supplied context. It is best to pass in the current Activity. 2780558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan * 2790558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan * @param context The activity if at all possible. 2800558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan */ 2810558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan public static CalendarController getInstance(Context context) { 2820558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan synchronized (instances) { 2830558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan CalendarController controller = instances.get(context); 2840558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan if (controller == null) { 2850558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan controller = new CalendarController(context); 2860558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan instances.put(context, controller); 2870558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan } 2880558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan return controller; 2890558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan } 2900558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan } 2910558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan 292ed61b48c048c5e8f6646f528561988fd25fe7416Erik /** 293ed61b48c048c5e8f6646f528561988fd25fe7416Erik * Removes an instance when it is no longer needed. This should be called in 294ed61b48c048c5e8f6646f528561988fd25fe7416Erik * an activity's onDestroy method. 295ed61b48c048c5e8f6646f528561988fd25fe7416Erik * 296ed61b48c048c5e8f6646f528561988fd25fe7416Erik * @param context The activity used to create the controller 297ed61b48c048c5e8f6646f528561988fd25fe7416Erik */ 298ed61b48c048c5e8f6646f528561988fd25fe7416Erik public static void removeInstance(Context context) { 299ed61b48c048c5e8f6646f528561988fd25fe7416Erik instances.remove(context); 300ed61b48c048c5e8f6646f528561988fd25fe7416Erik } 301ed61b48c048c5e8f6646f528561988fd25fe7416Erik 3020558defd2215696cee0768ce2bf2cb4da56efc42Michael Chan private CalendarController(Context context) { 303ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan mContext = context; 3044679f6009e8d754e4d76c68a0c5a0a32b23f7f0cRoboErik mUpdateTimezone.run(); 3053458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan mTime.setToNow(); 30685e550966b125220af5faa7407a0cfc0b54494aaMichael Chan mDetailViewType = Utils.getSharedPreference(mContext, 3074b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa GeneralPreferences.KEY_DETAILED_VIEW, 3084b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa GeneralPreferences.DEFAULT_DETAILED_VIEW); 30983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 3104970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan 311deced8999da73effe4133e2317c262fea7910090Michael Chan public void sendEventRelatedEvent(Object sender, long eventType, long eventId, long startMillis, 31287f993ff96172f508d3f241f8a425f953c7eb739RoboErik long endMillis, int x, int y, long selectedMillis) { 3136bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson // TODO: pass the real allDay status or at least a status that says we don't know the 3146bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson // status and have the receiver query the data. 3156bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson // The current use of this method for VIEW_EVENT is by the day view to show an EventInfo 3166bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson // so currently the missing allDay status has no effect. 317edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan sendEventRelatedEventWithExtra(sender, eventType, eventId, startMillis, endMillis, x, y, 3186bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson EventInfo.buildViewExtraLong(Attendees.ATTENDEE_STATUS_NONE, false), 3196bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson selectedMillis); 320deced8999da73effe4133e2317c262fea7910090Michael Chan } 321deced8999da73effe4133e2317c262fea7910090Michael Chan 3224970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan /** 32383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * Helper for sending New/View/Edit/Delete events 32483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * 32583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * @param sender object of the caller 32683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * @param eventType one of {@link EventType} 32783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * @param eventId event id 3283458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan * @param startMillis start time 3293458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan * @param endMillis end time 33083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * @param x x coordinate in the activity space 33183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * @param y y coordinate in the activity space 3326bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson * @param extraLong default response value for the "simple event view" and all day indication. 3336bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson * Use Attendees.ATTENDEE_STATUS_NONE for no response. 33487f993ff96172f508d3f241f8a425f953c7eb739RoboErik * @param selectedMillis The time to specify as selected 3354970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan */ 336edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan public void sendEventRelatedEventWithExtra(Object sender, long eventType, long eventId, 33787f993ff96172f508d3f241f8a425f953c7eb739RoboErik long startMillis, long endMillis, int x, int y, long extraLong, long selectedMillis) { 33883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan EventInfo info = new EventInfo(); 33983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan info.eventType = eventType; 340a7694eead7cbb293990bc89c3906e17bad36194cErik if (eventType == EventType.EDIT_EVENT || eventType == EventType.VIEW_EVENT_DETAILS) { 3415f62079ab9daefe95ede87631766e99e8b4a2220Erik info.viewType = ViewType.CURRENT; 342dd95df57c8c5a58a85c4c0effad5652dec14f621Erik } 34383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan info.id = eventId; 3444679f6009e8d754e4d76c68a0c5a0a32b23f7f0cRoboErik info.startTime = new Time(Utils.getTimeZone(mContext, mUpdateTimezone)); 3459e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan info.startTime.set(startMillis); 34687f993ff96172f508d3f241f8a425f953c7eb739RoboErik if (selectedMillis != -1) { 3474679f6009e8d754e4d76c68a0c5a0a32b23f7f0cRoboErik info.selectedTime = new Time(Utils.getTimeZone(mContext, mUpdateTimezone)); 34887f993ff96172f508d3f241f8a425f953c7eb739RoboErik info.selectedTime.set(selectedMillis); 34987f993ff96172f508d3f241f8a425f953c7eb739RoboErik } else { 35087f993ff96172f508d3f241f8a425f953c7eb739RoboErik info.selectedTime = info.startTime; 35187f993ff96172f508d3f241f8a425f953c7eb739RoboErik } 3524679f6009e8d754e4d76c68a0c5a0a32b23f7f0cRoboErik info.endTime = new Time(Utils.getTimeZone(mContext, mUpdateTimezone)); 3539e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan info.endTime.set(endMillis); 35483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan info.x = x; 35583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan info.y = y; 356deced8999da73effe4133e2317c262fea7910090Michael Chan info.extraLong = extraLong; 35783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan this.sendEvent(sender, info); 35883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 3594970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan 3604970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan /** 36183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * Helper for sending non-calendar-event events 36283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * 36383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * @param sender object of the caller 36483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * @param eventType one of {@link EventType} 36583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * @param start start time 36683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * @param end end time 367d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan * @param eventId event id 36883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan * @param viewType {@link ViewType} 3694970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan */ 37025251192d80159d4cf0934f3ac5c84cb0b8b7365Erik public void sendEvent(Object sender, long eventType, Time start, Time end, long eventId, 3713458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan int viewType) { 372f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan sendEvent(sender, eventType, start, end, start, eventId, viewType, EXTRA_GOTO_TIME, null, 373f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan null); 3746d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa } 3756d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa 3766d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa /** 37746a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan * sendEvent() variant with extraLong, search query, and search component name. 3786d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa */ 3796d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa public void sendEvent(Object sender, long eventType, Time start, Time end, long eventId, 38046a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan int viewType, long extraLong, String query, ComponentName componentName) { 381f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan sendEvent(sender, eventType, start, end, start, eventId, viewType, extraLong, query, 382f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan componentName); 383f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan } 384f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan 385f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan public void sendEvent(Object sender, long eventType, Time start, Time end, Time selected, 386f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan long eventId, int viewType, long extraLong, String query, ComponentName componentName) { 38783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan EventInfo info = new EventInfo(); 38883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan info.eventType = eventType; 38983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan info.startTime = start; 390f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan info.selectedTime = selected; 39183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan info.endTime = end; 39283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan info.id = eventId; 39383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan info.viewType = viewType; 3946d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa info.query = query; 3956d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa info.componentName = componentName; 39646a8b1117b0510a8dfd50586d5d22aa86b8dc1b9Michael Chan info.extraLong = extraLong; 39783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan this.sendEvent(sender, info); 39883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 39983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 40025251192d80159d4cf0934f3ac5c84cb0b8b7365Erik public void sendEvent(Object sender, final EventInfo event) { 40183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan // TODO Throw exception on invalid events 40283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 4033f348f3ea8a7927566a1283b6d6bb5e220662889Erik if (DEBUG) { 4043f348f3ea8a7927566a1283b6d6bb5e220662889Erik Log.d(TAG, eventInfoToString(event)); 4053f348f3ea8a7927566a1283b6d6bb5e220662889Erik } 40683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 40783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan Long filteredTypes = filters.get(sender); 40883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan if (filteredTypes != null && (filteredTypes.longValue() & event.eventType) != 0) { 40983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan // Suppress event per filter 4103f348f3ea8a7927566a1283b6d6bb5e220662889Erik if (DEBUG) { 4113f348f3ea8a7927566a1283b6d6bb5e220662889Erik Log.d(TAG, "Event suppressed"); 4123f348f3ea8a7927566a1283b6d6bb5e220662889Erik } 41383b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan return; 41483b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 41583b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 416ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan mPreviousViewType = mViewType; 41783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 4183458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan // Fix up view if not specified 419d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan if (event.viewType == ViewType.DETAIL) { 42085e550966b125220af5faa7407a0cfc0b54494aaMichael Chan event.viewType = mDetailViewType; 42185e550966b125220af5faa7407a0cfc0b54494aaMichael Chan mViewType = mDetailViewType; 422d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan } else if (event.viewType == ViewType.CURRENT) { 4233458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan event.viewType = mViewType; 424f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan } else if (event.viewType != ViewType.EDIT) { 425ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan mViewType = event.viewType; 42685e550966b125220af5faa7407a0cfc0b54494aaMichael Chan 42763cd053150e00fde045b019dbe0f48b8a9ed3559Erik if (event.viewType == ViewType.AGENDA || event.viewType == ViewType.DAY 42863cd053150e00fde045b019dbe0f48b8a9ed3559Erik || (Utils.getAllowWeekForDetailView() && event.viewType == ViewType.WEEK)) { 42985e550966b125220af5faa7407a0cfc0b54494aaMichael Chan mDetailViewType = mViewType; 43085e550966b125220af5faa7407a0cfc0b54494aaMichael Chan } 4313458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan } 4323458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan 433f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan if (DEBUG) { 434f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Log.e(TAG, "vvvvvvvvvvvvvvv"); 435f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Log.e(TAG, "Start " + (event.startTime == null ? "null" : event.startTime.toString())); 436f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Log.e(TAG, "End " + (event.endTime == null ? "null" : event.endTime.toString())); 437f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Log.e(TAG, "Select " + (event.selectedTime == null ? "null" : event.selectedTime.toString())); 438f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Log.e(TAG, "mTime " + (mTime == null ? "null" : mTime.toString())); 439f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan } 440f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan 441f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan long startMillis = 0; 442f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan if (event.startTime != null) { 443f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan startMillis = event.startTime.toMillis(false); 444f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan } 445f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan 446f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan // Set mTime if selectedTime is set 447f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan if (event.selectedTime != null && event.selectedTime.toMillis(false) != 0) { 448f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mTime.set(event.selectedTime); 449f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan } else { 450f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan if (startMillis != 0) { 451f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan // selectedTime is not set so set mTime to startTime iff it is not 452f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan // within start and end times 453f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan long mtimeMillis = mTime.toMillis(false); 454f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan if (mtimeMillis < startMillis 455f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan || (event.endTime != null && mtimeMillis > event.endTime.toMillis(false))) { 456f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan mTime.set(event.startTime); 457f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan } 458f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan } 459f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan event.selectedTime = mTime; 460f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan } 461c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik // Store the formatting flags if this is an update to the title 462c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik if (event.eventType == EventType.UPDATE_TITLE) { 463c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik mDateFlags = event.extraLong; 464c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik } 465f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan 4664003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang // Fix up start time if not specified 467f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan if (startMillis == 0) { 468f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan event.startTime = mTime; 469f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan } 470f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan if (DEBUG) { 471f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Log.e(TAG, "Start " + (event.startTime == null ? "null" : event.startTime.toString())); 472f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Log.e(TAG, "End " + (event.endTime == null ? "null" : event.endTime.toString())); 473f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Log.e(TAG, "Select " + (event.selectedTime == null ? "null" : event.selectedTime.toString())); 474f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Log.e(TAG, "mTime " + (mTime == null ? "null" : mTime.toString())); 475f0868f61983ff1b04a49f1b6f2ef6d49311011e8Michael Chan Log.e(TAG, "^^^^^^^^^^^^^^^"); 4764003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang } 4774003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang 4787b92da258a480284dcc15a518ea570072329a31dErik // Store the eventId if we're entering edit event 479a7694eead7cbb293990bc89c3906e17bad36194cErik if ((event.eventType 480a7694eead7cbb293990bc89c3906e17bad36194cErik & (EventType.CREATE_EVENT | EventType.EDIT_EVENT | EventType.VIEW_EVENT_DETAILS)) 481a7694eead7cbb293990bc89c3906e17bad36194cErik != 0) { 4827b92da258a480284dcc15a518ea570072329a31dErik if (event.id > 0) { 4837b92da258a480284dcc15a518ea570072329a31dErik mEventId = event.id; 4847b92da258a480284dcc15a518ea570072329a31dErik } else { 4857b92da258a480284dcc15a518ea570072329a31dErik mEventId = -1; 4867b92da258a480284dcc15a518ea570072329a31dErik } 4877b92da258a480284dcc15a518ea570072329a31dErik } 4887b92da258a480284dcc15a518ea570072329a31dErik 4894003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang boolean handled = false; 490ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan synchronized (this) { 491ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson mDispatchInProgressCounter ++; 492ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan 4933f348f3ea8a7927566a1283b6d6bb5e220662889Erik if (DEBUG) { 4943f348f3ea8a7927566a1283b6d6bb5e220662889Erik Log.d(TAG, "sendEvent: Dispatching to " + eventHandlers.size() + " handlers"); 4953f348f3ea8a7927566a1283b6d6bb5e220662889Erik } 496ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan // Dispatch to event handler(s) 4973864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik if (mFirstEventHandler != null) { 4983864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik // Handle the 'first' one before handling the others 4993864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik EventHandler handler = mFirstEventHandler.second; 5003864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik if (handler != null && (handler.getSupportedEventTypes() & event.eventType) != 0 5013864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik && !mToBeRemovedEventHandlers.contains(mFirstEventHandler.first)) { 5023864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik handler.handleEvent(event); 5033864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik handled = true; 5043864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik } 5053864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik } 5063f348f3ea8a7927566a1283b6d6bb5e220662889Erik for (Iterator<Entry<Integer, EventHandler>> handlers = 5073f348f3ea8a7927566a1283b6d6bb5e220662889Erik eventHandlers.entrySet().iterator(); handlers.hasNext();) { 5083f348f3ea8a7927566a1283b6d6bb5e220662889Erik Entry<Integer, EventHandler> entry = handlers.next(); 5093f348f3ea8a7927566a1283b6d6bb5e220662889Erik int key = entry.getKey(); 5103864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik if (mFirstEventHandler != null && key == mFirstEventHandler.first) { 5113864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik // If this was the 'first' handler it was already handled 5123864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik continue; 5133864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik } 5143f348f3ea8a7927566a1283b6d6bb5e220662889Erik EventHandler eventHandler = entry.getValue(); 515ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan if (eventHandler != null 516ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan && (eventHandler.getSupportedEventTypes() & event.eventType) != 0) { 5173f348f3ea8a7927566a1283b6d6bb5e220662889Erik if (mToBeRemovedEventHandlers.contains(key)) { 518ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan continue; 519ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan } 520ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan eventHandler.handleEvent(event); 5214003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang handled = true; 522ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan } 523ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan } 5243458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan 525ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson mDispatchInProgressCounter --; 526cb81189e4868769ea016253eca104e46df2f033aErik 527ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson if (mDispatchInProgressCounter == 0) { 528ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson 529ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson // Deregister removed handlers 530ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson if (mToBeRemovedEventHandlers.size() > 0) { 531ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson for (Integer zombie : mToBeRemovedEventHandlers) { 532ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson eventHandlers.remove(zombie); 5333864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik if (mFirstEventHandler != null && zombie.equals(mFirstEventHandler.first)) { 5343864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik mFirstEventHandler = null; 5353864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik } 536ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson } 537ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson mToBeRemovedEventHandlers.clear(); 53883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 539ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson // Add new handlers 5403864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik if (mToBeAddedFirstEventHandler != null) { 5413864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik mFirstEventHandler = mToBeAddedFirstEventHandler; 5423864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik mToBeAddedFirstEventHandler = null; 5433864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik } 544ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson if (mToBeAddedEventHandlers.size() > 0) { 545ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson for (Entry<Integer, EventHandler> food : mToBeAddedEventHandlers.entrySet()) { 546ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson eventHandlers.put(food.getKey(), food.getValue()); 547ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson } 548cb81189e4868769ea016253eca104e46df2f033aErik } 549cb81189e4868769ea016253eca104e46df2f033aErik } 55083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 5514003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang 5524003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang if (!handled) { 5536b858fc6f8afad95a075595016c5c22547924886Erik // Launch Settings 5546b858fc6f8afad95a075595016c5c22547924886Erik if (event.eventType == EventType.LAUNCH_SETTINGS) { 5554003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang launchSettings(); 5564003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang return; 5574003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang } 5584003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang 5592aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // Launch Calendar Visible Selector 5602aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (event.eventType == EventType.LAUNCH_SELECT_VISIBLE_CALENDARS) { 5612aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan launchSelectVisibleCalendars(); 5622aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan return; 5632aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 5642aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 5654003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang // Create/View/Edit/Delete Event 5664003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang long endTime = (event.endTime == null) ? -1 : event.endTime.toMillis(false); 5674003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang if (event.eventType == EventType.CREATE_EVENT) { 568edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan launchCreateEvent(event.startTime.toMillis(false), endTime, 569edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan event.extraLong == EXTRA_CREATE_ALL_DAY); 5704003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang return; 5714003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang } else if (event.eventType == EventType.VIEW_EVENT) { 5726bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson launchViewEvent(event.id, event.startTime.toMillis(false), endTime, 5736bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson event.getResponse()); 5744003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang return; 5754003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang } else if (event.eventType == EventType.EDIT_EVENT) { 576a7694eead7cbb293990bc89c3906e17bad36194cErik launchEditEvent(event.id, event.startTime.toMillis(false), endTime, true); 577a7694eead7cbb293990bc89c3906e17bad36194cErik return; 578a7694eead7cbb293990bc89c3906e17bad36194cErik } else if (event.eventType == EventType.VIEW_EVENT_DETAILS) { 579a7694eead7cbb293990bc89c3906e17bad36194cErik launchEditEvent(event.id, event.startTime.toMillis(false), endTime, false); 5804003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang return; 5814003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang } else if (event.eventType == EventType.DELETE_EVENT) { 5824003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang launchDeleteEvent(event.id, event.startTime.toMillis(false), endTime); 5834003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang return; 5846d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa } else if (event.eventType == EventType.SEARCH) { 5856d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa launchSearch(event.id, event.query, event.componentName); 5866d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa return; 5874003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang } 5884003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang } 58983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 59083b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 5913f348f3ea8a7927566a1283b6d6bb5e220662889Erik /** 5923f348f3ea8a7927566a1283b6d6bb5e220662889Erik * Adds or updates an event handler. This uses a LinkedHashMap so that we can 5933f348f3ea8a7927566a1283b6d6bb5e220662889Erik * replace fragments based on the view id they are being expanded into. 5943f348f3ea8a7927566a1283b6d6bb5e220662889Erik * 5953f348f3ea8a7927566a1283b6d6bb5e220662889Erik * @param key The view id or placeholder for this handler 5963f348f3ea8a7927566a1283b6d6bb5e220662889Erik * @param eventHandler Typically a fragment or activity in the calendar app 5973f348f3ea8a7927566a1283b6d6bb5e220662889Erik */ 5983f348f3ea8a7927566a1283b6d6bb5e220662889Erik public void registerEventHandler(int key, EventHandler eventHandler) { 599ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan synchronized (this) { 600ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson if (mDispatchInProgressCounter > 0) { 601cb81189e4868769ea016253eca104e46df2f033aErik mToBeAddedEventHandlers.put(key, eventHandler); 602cb81189e4868769ea016253eca104e46df2f033aErik } else { 603cb81189e4868769ea016253eca104e46df2f033aErik eventHandlers.put(key, eventHandler); 604cb81189e4868769ea016253eca104e46df2f033aErik } 605ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan } 60683b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 60783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 6083864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik public void registerFirstEventHandler(int key, EventHandler eventHandler) { 6093864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik synchronized (this) { 6103864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik registerEventHandler(key, eventHandler); 6113864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik if (mDispatchInProgressCounter > 0) { 6123864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik mToBeAddedFirstEventHandler = new Pair<Integer, EventHandler>(key, eventHandler); 6133864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik } else { 6143864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik mFirstEventHandler = new Pair<Integer, EventHandler>(key, eventHandler); 6153864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik } 6163864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik } 6173864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik } 6183864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik 6193f348f3ea8a7927566a1283b6d6bb5e220662889Erik public void deregisterEventHandler(Integer key) { 620ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan synchronized (this) { 621ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson if (mDispatchInProgressCounter > 0) { 622ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan // To avoid ConcurrencyException, stash away the event handler for now. 6233f348f3ea8a7927566a1283b6d6bb5e220662889Erik mToBeRemovedEventHandlers.add(key); 624ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan } else { 6253f348f3ea8a7927566a1283b6d6bb5e220662889Erik eventHandlers.remove(key); 6263864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik if (mFirstEventHandler != null && mFirstEventHandler.first == key) { 6273864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik mFirstEventHandler = null; 6283864be025ed7fa5bcb33c7adaae9267d5b34f17fRoboErik } 629ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan } 630ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan } 63183b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 63283b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 63361310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook public void deregisterAllEventHandlers() { 63461310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook synchronized (this) { 63561310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook if (mDispatchInProgressCounter > 0) { 63661310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook // To avoid ConcurrencyException, stash away the event handler for now. 63761310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook mToBeRemovedEventHandlers.addAll(eventHandlers.keySet()); 63861310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook } else { 63961310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook eventHandlers.clear(); 64061310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook mFirstEventHandler = null; 64161310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook } 64261310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook } 64361310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook } 64461310b7263c6d6477f252789f6288991d51ec8ccPaul Westbrook 6453458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan // FRAG_TODO doesn't work yet 64625251192d80159d4cf0934f3ac5c84cb0b8b7365Erik public void filterBroadcasts(Object sender, long eventTypes) { 64783b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan filters.put(sender, eventTypes); 64883b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan } 64983b0fe36b523192a504a1d2baf2f36676a80b9d5Michael Chan 6508e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang /** 6518e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang * @return the time that this controller is currently pointed at 6528e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang */ 6538e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang public long getTime() { 6548e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang return mTime.toMillis(false); 6558e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang } 6568e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang 6577b92da258a480284dcc15a518ea570072329a31dErik /** 658c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik * @return the last set of date flags sent with 659c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik * {@link EventType#UPDATE_TITLE} 660c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik */ 661c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik public long getDateFlags() { 662c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik return mDateFlags; 663c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik } 664c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik 665c8e0f21af5e2508d6e53a59e0f997dffd6a5321cRoboErik /** 666144edfa3f69dd13d2ae5f107a8f4d422f11dc620Erik * Set the time this controller is currently pointed at 667144edfa3f69dd13d2ae5f107a8f4d422f11dc620Erik * 668144edfa3f69dd13d2ae5f107a8f4d422f11dc620Erik * @param millisTime Time since epoch in millis 669144edfa3f69dd13d2ae5f107a8f4d422f11dc620Erik */ 670144edfa3f69dd13d2ae5f107a8f4d422f11dc620Erik public void setTime(long millisTime) { 671144edfa3f69dd13d2ae5f107a8f4d422f11dc620Erik mTime.set(millisTime); 672144edfa3f69dd13d2ae5f107a8f4d422f11dc620Erik } 673144edfa3f69dd13d2ae5f107a8f4d422f11dc620Erik 674144edfa3f69dd13d2ae5f107a8f4d422f11dc620Erik /** 6757b92da258a480284dcc15a518ea570072329a31dErik * @return the last event ID the edit view was launched with 6767b92da258a480284dcc15a518ea570072329a31dErik */ 6777b92da258a480284dcc15a518ea570072329a31dErik public long getEventId() { 6787b92da258a480284dcc15a518ea570072329a31dErik return mEventId; 6797b92da258a480284dcc15a518ea570072329a31dErik } 6807b92da258a480284dcc15a518ea570072329a31dErik 681ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan public int getViewType() { 682ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan return mViewType; 683ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan } 684ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan 685ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan public int getPreviousViewType() { 686ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan return mPreviousViewType; 687ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan } 6888e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang 6892aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private void launchSelectVisibleCalendars() { 6902aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Intent intent = new Intent(Intent.ACTION_VIEW); 69107d9fee87bc02849c0dd7b66326a320d53cf5479Michael Chan intent.setClass(mContext, SelectVisibleCalendarsActivity.class); 6922aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP); 6932aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mContext.startActivity(intent); 6942aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 6952aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 6969e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan private void launchSettings() { 6979e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan Intent intent = new Intent(Intent.ACTION_VIEW); 69807d9fee87bc02849c0dd7b66326a320d53cf5479Michael Chan intent.setClass(mContext, CalendarSettingsActivity.class); 6999e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP); 700ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan mContext.startActivity(intent); 7019e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan } 7029e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan 703edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan private void launchCreateEvent(long startMillis, long endMillis, boolean allDayEvent) { 7049e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan Intent intent = new Intent(Intent.ACTION_VIEW); 70507d9fee87bc02849c0dd7b66326a320d53cf5479Michael Chan intent.setClass(mContext, EditEventActivity.class); 706a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik intent.putExtra(EXTRA_EVENT_BEGIN_TIME, startMillis); 707a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik intent.putExtra(EXTRA_EVENT_END_TIME, endMillis); 708edecd9a97e02ff14bd5abeec3414e1bf3cc631dfMichael Chan intent.putExtra(EXTRA_EVENT_ALL_DAY, allDayEvent); 7097b92da258a480284dcc15a518ea570072329a31dErik mEventId = -1; 710ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan mContext.startActivity(intent); 7119e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan } 7129e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan 7136bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson public void launchViewEvent(long eventId, long startMillis, long endMillis, int response) { 7149e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan Intent intent = new Intent(Intent.ACTION_VIEW); 7159e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId); 7169e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan intent.setData(eventUri); 71707d9fee87bc02849c0dd7b66326a320d53cf5479Michael Chan intent.setClass(mContext, AllInOneActivity.class); 718a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik intent.putExtra(EXTRA_EVENT_BEGIN_TIME, startMillis); 719a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik intent.putExtra(EXTRA_EVENT_END_TIME, endMillis); 7206bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson intent.putExtra(ATTENDEE_STATUS, response); 7214024dee06fbe7c4bbd5b56e7d58917e86b66802eIsaac Katzenelson intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 722ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan mContext.startActivity(intent); 7239e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan } 7249e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan 725a7694eead7cbb293990bc89c3906e17bad36194cErik private void launchEditEvent(long eventId, long startMillis, long endMillis, boolean edit) { 7269e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId); 7279e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan Intent intent = new Intent(Intent.ACTION_EDIT, uri); 728a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik intent.putExtra(EXTRA_EVENT_BEGIN_TIME, startMillis); 729a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik intent.putExtra(EXTRA_EVENT_END_TIME, endMillis); 730ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan intent.setClass(mContext, EditEventActivity.class); 731a7694eead7cbb293990bc89c3906e17bad36194cErik intent.putExtra(EVENT_EDIT_ON_LAUNCH, edit); 7327b92da258a480284dcc15a518ea570072329a31dErik mEventId = eventId; 733ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan mContext.startActivity(intent); 7349e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan } 7359e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan 7361881a896a82c425845e3ef2a1a716d329f0e45f1Michael Chan// private void launchAlerts() { 7371881a896a82c425845e3ef2a1a716d329f0e45f1Michael Chan// Intent intent = new Intent(); 7381881a896a82c425845e3ef2a1a716d329f0e45f1Michael Chan// intent.setClass(mContext, AlertActivity.class); 7391881a896a82c425845e3ef2a1a716d329f0e45f1Michael Chan// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 7401881a896a82c425845e3ef2a1a716d329f0e45f1Michael Chan// mContext.startActivity(intent); 7411881a896a82c425845e3ef2a1a716d329f0e45f1Michael Chan// } 7421881a896a82c425845e3ef2a1a716d329f0e45f1Michael Chan 7439e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan private void launchDeleteEvent(long eventId, long startMillis, long endMillis) { 7449e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan launchDeleteEventAndFinish(null, eventId, startMillis, endMillis, -1); 7459e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan } 7469e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan 7479e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan private void launchDeleteEventAndFinish(Activity parentActivity, long eventId, long startMillis, 7489e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan long endMillis, int deleteWhich) { 749ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan DeleteEventHelper deleteEventHelper = new DeleteEventHelper(mContext, parentActivity, 7509e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan parentActivity != null /* exit when done */); 7519e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan deleteEventHelper.delete(startMillis, endMillis, eventId, deleteWhich); 7529e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan } 7533458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan 7546d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa private void launchSearch(long eventId, String query, ComponentName componentName) { 7556d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa final SearchManager searchManager = 7566d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa (SearchManager)mContext.getSystemService(Context.SEARCH_SERVICE); 7576d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa final SearchableInfo searchableInfo = searchManager.getSearchableInfo(componentName); 7586d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa final Intent intent = new Intent(Intent.ACTION_SEARCH); 7596d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa intent.putExtra(SearchManager.QUERY, query); 7606d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa intent.setComponent(searchableInfo.getSearchActivity()); 7612bd5cc06a7a89a848688416456f1b8f915542d57RoboErik intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 7626d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa mContext.startActivity(intent); 7636d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa } 7646d2e6f78726cc167e561148a3efb27aa15524b82Daisuke Miyakawa 7657dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden /** 7667dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden * Performs a manual refresh of calendars in all known accounts. 7677dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden */ 768ba1b94afd187279623a57417da1ef78efa1217e2Erik public void refreshCalendars() { 7697dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden Account[] accounts = AccountManager.get(mContext).getAccounts(); 7707dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden Log.d(TAG, "Refreshing " + accounts.length + " accounts"); 7717dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden 7727dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden String authority = Calendars.CONTENT_URI.getAuthority(); 7737dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden for (int i = 0; i < accounts.length; i++) { 7747dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden if (Log.isLoggable(TAG, Log.DEBUG)) { 7757dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden Log.d(TAG, "Refreshing calendars for: " + accounts[i]); 7767dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden } 7777dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden Bundle extras = new Bundle(); 7787dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); 7797dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden ContentResolver.requestSync(accounts[i], authority, extras); 7807dcd301cab15959d0d745f0a460f1dce2065d44eAndy McFadden } 781ba1b94afd187279623a57417da1ef78efa1217e2Erik } 782ba1b94afd187279623a57417da1ef78efa1217e2Erik 783dd95df57c8c5a58a85c4c0effad5652dec14f621Erik // Forces the viewType. Should only be used for initialization. 784dd95df57c8c5a58a85c4c0effad5652dec14f621Erik public void setViewType(int viewType) { 785dd95df57c8c5a58a85c4c0effad5652dec14f621Erik mViewType = viewType; 786dd95df57c8c5a58a85c4c0effad5652dec14f621Erik } 787dd95df57c8c5a58a85c4c0effad5652dec14f621Erik 7887b92da258a480284dcc15a518ea570072329a31dErik // Sets the eventId. Should only be used for initialization. 7897b92da258a480284dcc15a518ea570072329a31dErik public void setEventId(long eventId) { 7907b92da258a480284dcc15a518ea570072329a31dErik mEventId = eventId; 7917b92da258a480284dcc15a518ea570072329a31dErik } 7927b92da258a480284dcc15a518ea570072329a31dErik 7933458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan private String eventInfoToString(EventInfo eventInfo) { 7943458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan String tmp = "Unknown"; 7953458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan 7963458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan StringBuilder builder = new StringBuilder(); 797ab29d9ea9a4fe6b835c7f484a2273e92e8bc323dMichael Chan if ((eventInfo.eventType & EventType.GO_TO) != 0) { 7983458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan tmp = "Go to time/event"; 7993458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan } else if ((eventInfo.eventType & EventType.CREATE_EVENT) != 0) { 8003458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan tmp = "New event"; 8013458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan } else if ((eventInfo.eventType & EventType.VIEW_EVENT) != 0) { 8023458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan tmp = "View event"; 8036d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } else if ((eventInfo.eventType & EventType.VIEW_EVENT_DETAILS) != 0) { 8046d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan tmp = "View details"; 8053458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan } else if ((eventInfo.eventType & EventType.EDIT_EVENT) != 0) { 8063458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan tmp = "Edit event"; 8073458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan } else if ((eventInfo.eventType & EventType.DELETE_EVENT) != 0) { 8083458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan tmp = "Delete event"; 8092aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } else if ((eventInfo.eventType & EventType.LAUNCH_SELECT_VISIBLE_CALENDARS) != 0) { 8102aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan tmp = "Launch select visible calendars"; 8113458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan } else if ((eventInfo.eventType & EventType.LAUNCH_SETTINGS) != 0) { 8123458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan tmp = "Launch settings"; 8133f348f3ea8a7927566a1283b6d6bb5e220662889Erik } else if ((eventInfo.eventType & EventType.EVENTS_CHANGED) != 0) { 8143f348f3ea8a7927566a1283b6d6bb5e220662889Erik tmp = "Refresh events"; 8154003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang } else if ((eventInfo.eventType & EventType.SEARCH) != 0) { 8164003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang tmp = "Search"; 8176d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } else if ((eventInfo.eventType & EventType.USER_HOME) != 0) { 8186d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan tmp = "Gone home"; 8196d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan } else if ((eventInfo.eventType & EventType.UPDATE_TITLE) != 0) { 8206d4ce6ed308da8b4d8f2e62660865e396713c025Michael Chan tmp = "Update title"; 8213458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan } 8223458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(tmp); 8233458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(": id="); 8243458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(eventInfo.id); 825d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan builder.append(", selected="); 826d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan builder.append(eventInfo.selectedTime); 827d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan builder.append(", start="); 8283458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(eventInfo.startTime); 829d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan builder.append(", end="); 8303458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(eventInfo.endTime); 8313458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(", viewType="); 8323458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(eventInfo.viewType); 8333458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(", x="); 8343458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(eventInfo.x); 8353458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(", y="); 8363458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan builder.append(eventInfo.y); 8373458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan return builder.toString(); 8383458a1775920dda53099b7f1913cd4ec4c8b4095Michael Chan } 8394970159b2e6674fc5d61425aa0fcff8e5fc15bdbMichael Chan} 840