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
19a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport android.content.ContentResolver;
20a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport android.content.ContentUris;
21146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context;
22146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.SharedPreferences;
23146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.res.Resources;
24146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.database.Cursor;
25a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport android.net.Uri;
26146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.os.Debug;
27a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees;
28a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport android.provider.CalendarContract.Calendars;
29a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Events;
30a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Instances;
31146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.TextUtils;
32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateUtils;
33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.util.Log;
34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
35146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.ArrayList;
36a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport java.util.Arrays;
37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Iterator;
38146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.concurrent.atomic.AtomicInteger;
39146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
40146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// TODO: should Event be Parcelable so it can be passed via Intents?
411d92cbdf5b754f9da92303eaf554d8db7d7b0849RoboErikpublic class Event implements Cloneable {
42146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
43981874e61ecf29a96a77601a3172b2503b6537eeErik    private static final String TAG = "CalEvent";
44146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final boolean PROFILE = false;
45146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
462fda24534978f55711526dbde747aa50d68dec40RoboErik    /**
472fda24534978f55711526dbde747aa50d68dec40RoboErik     * The sort order is:
48ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * 1) events with an earlier start (begin for normal events, startday for allday)
49ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * 2) events with a later end (end for normal events, endday for allday)
50ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * 3) the title (unnecessary, but nice)
512fda24534978f55711526dbde747aa50d68dec40RoboErik     *
522fda24534978f55711526dbde747aa50d68dec40RoboErik     * The start and end day is sorted first so that all day events are
532fda24534978f55711526dbde747aa50d68dec40RoboErik     * sorted correctly with respect to events that are >24 hours (and
542fda24534978f55711526dbde747aa50d68dec40RoboErik     * therefore show up in the allday area).
552fda24534978f55711526dbde747aa50d68dec40RoboErik     */
562fda24534978f55711526dbde747aa50d68dec40RoboErik    private static final String SORT_EVENTS_BY =
57ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            "begin ASC, end DESC, title ASC";
58ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static final String SORT_ALLDAY_BY =
59ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            "startDay ASC, endDay DESC, title ASC";
60ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static final String DISPLAY_AS_ALLDAY = "dispAllday";
61ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik
62ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static final String EVENTS_WHERE = DISPLAY_AS_ALLDAY + "=0";
63ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static final String ALLDAY_WHERE = DISPLAY_AS_ALLDAY + "=1";
642fda24534978f55711526dbde747aa50d68dec40RoboErik
65981874e61ecf29a96a77601a3172b2503b6537eeErik    // The projection to use when querying instances to build a list of events
66981874e61ecf29a96a77601a3172b2503b6537eeErik    public static final String[] EVENT_PROJECTION = new String[] {
67146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.TITLE,                 // 0
68146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.EVENT_LOCATION,        // 1
69146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.ALL_DAY,               // 2
70693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan            Instances.DISPLAY_COLOR,         // 3 If SDK < 16, set to Instances.CALENDAR_COLOR.
71146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.EVENT_TIMEZONE,        // 4
72146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.EVENT_ID,              // 5
73146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.BEGIN,                 // 6
74146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.END,                   // 7
75146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances._ID,                   // 8
76146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.START_DAY,             // 9
77146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.END_DAY,               // 10
78146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.START_MINUTE,          // 11
79146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.END_MINUTE,            // 12
80146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.HAS_ALARM,             // 13
81146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.RRULE,                 // 14
82146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.RDATE,                 // 15
83146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.SELF_ATTENDEE_STATUS,  // 16
846d34cec523930368976bc8d358d0a6de1da3462cMichael Chan            Events.ORGANIZER,                // 17
856d34cec523930368976bc8d358d0a6de1da3462cMichael Chan            Events.GUESTS_CAN_MODIFY,        // 18
86ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            Instances.ALL_DAY + "=1 OR (" + Instances.END + "-" + Instances.BEGIN + ")>="
87ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                    + DateUtils.DAY_IN_MILLIS + " AS " + DISPLAY_AS_ALLDAY, // 19
88146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    };
89146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
90146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // The indices for the projection array above.
91146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_TITLE_INDEX = 0;
92146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_LOCATION_INDEX = 1;
93146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_ALL_DAY_INDEX = 2;
94146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_COLOR_INDEX = 3;
95146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_TIMEZONE_INDEX = 4;
96146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_EVENT_ID_INDEX = 5;
97146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_BEGIN_INDEX = 6;
98146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_END_INDEX = 7;
99146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_START_DAY_INDEX = 9;
100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_END_DAY_INDEX = 10;
101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_START_MINUTE_INDEX = 11;
102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_END_MINUTE_INDEX = 12;
103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_HAS_ALARM_INDEX = 13;
104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_RRULE_INDEX = 14;
105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_RDATE_INDEX = 15;
106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_SELF_ATTENDEE_STATUS_INDEX = 16;
1076d34cec523930368976bc8d358d0a6de1da3462cMichael Chan    private static final int PROJECTION_ORGANIZER_INDEX = 17;
1086d34cec523930368976bc8d358d0a6de1da3462cMichael Chan    private static final int PROJECTION_GUESTS_CAN_INVITE_OTHERS_INDEX = 18;
109ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static final int PROJECTION_DISPLAY_AS_ALLDAY = 19;
110ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik
111693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan    static {
112fac2d1594f7ecae8e50dc7790ce67de0c9b70d22Sara Ting        if (!Utils.isJellybeanOrLater()) {
113693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan            EVENT_PROJECTION[PROJECTION_COLOR_INDEX] = Instances.CALENDAR_COLOR;
114693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan        }
115693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan    }
116693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan
117ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static String mNoTitleString;
118ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static int mNoColorColor;
119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long id;
121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int color;
122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public CharSequence title;
123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public CharSequence location;
124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean allDay;
1256d34cec523930368976bc8d358d0a6de1da3462cMichael Chan    public String organizer;
1266d34cec523930368976bc8d358d0a6de1da3462cMichael Chan    public boolean guestsCanModify;
127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int startDay;       // start Julian day
129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int endDay;         // end Julian day
130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int startTime;      // Start and end time are in minutes since midnight
131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int endTime;
132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long startMillis;   // UTC milliseconds since the epoch
134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long endMillis;     // UTC milliseconds since the epoch
135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mColumn;
136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mMaxColumns;
137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean hasAlarm;
139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean isRepeating;
140981874e61ecf29a96a77601a3172b2503b6537eeErik
141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int selfAttendeeStatus;
142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // The coordinates of the event rectangle drawn on the screen.
144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float left;
145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float right;
146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float top;
147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float bottom;
148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // These 4 fields are used for navigating among events within the selected
150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // hour in the Day and Week view.
151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextRight;
152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextLeft;
153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextUp;
154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextDown;
155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
15798ab9de2fa5ad8dfd37faa6593dc66fa426d8960Michael Chan    public final Object clone() throws CloneNotSupportedException {
15898ab9de2fa5ad8dfd37faa6593dc66fa426d8960Michael Chan        super.clone();
159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Event e = new Event();
160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.title = title;
162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.color = color;
163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.location = location;
164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.allDay = allDay;
165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startDay = startDay;
166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endDay = endDay;
167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startTime = startTime;
168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endTime = endTime;
169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startMillis = startMillis;
170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endMillis = endMillis;
171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.hasAlarm = hasAlarm;
172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.isRepeating = isRepeating;
173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.selfAttendeeStatus = selfAttendeeStatus;
1746d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        e.organizer = organizer;
1756d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        e.guestsCanModify = guestsCanModify;
176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return e;
178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public final void copyTo(Event dest) {
181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.id = id;
182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.title = title;
183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.color = color;
184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.location = location;
185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.allDay = allDay;
186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.startDay = startDay;
187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.endDay = endDay;
188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.startTime = startTime;
189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.endTime = endTime;
190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.startMillis = startMillis;
191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.endMillis = endMillis;
192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.hasAlarm = hasAlarm;
193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.isRepeating = isRepeating;
194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.selfAttendeeStatus = selfAttendeeStatus;
1956d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        dest.organizer = organizer;
1966d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        dest.guestsCanModify = guestsCanModify;
197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final Event newInstance() {
200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Event e = new Event();
201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.id = 0;
203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.title = null;
204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.color = 0;
205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.location = null;
206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.allDay = false;
207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startDay = 0;
208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endDay = 0;
209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startTime = 0;
210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endTime = 0;
211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startMillis = 0;
212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endMillis = 0;
213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.hasAlarm = false;
214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.isRepeating = false;
215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.selfAttendeeStatus = Attendees.ATTENDEE_STATUS_NONE;
216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return e;
218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
221b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik     * Loads <i>days</i> days worth of instances starting at <i>startDay</i>.
222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
223b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik    public static void loadEvents(Context context, ArrayList<Event> events, int startDay, int days,
224b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            int requestId, AtomicInteger sequenceNumber) {
225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (PROFILE) {
227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Debug.startMethodTracing("loadEvents");
228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
230ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        Cursor cEvents = null;
231ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        Cursor cAllday = null;
232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        events.clear();
234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        try {
235b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            int endDay = startDay + days - 1;
236b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik
237b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            // We use the byDay instances query to get a list of all events for
238b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            // the days we're interested in.
239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // The sort order is: events with an earlier start time occur
240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // first and if the start times are the same, then events with
241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // a later end time occur first. The later end time is ordered
242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // first so that long rectangles in the calendar views appear on
243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // the left side.  If the start and end times of two events are
244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // the same then we sort alphabetically on the title.  This isn't
245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // required for correctness, it just adds a nice touch.
246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Respect the preference to show/hide declined events
2484b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa            SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
2494b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa            boolean hideDeclined = prefs.getBoolean(GeneralPreferences.KEY_HIDE_DECLINED,
250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    false);
251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
252ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            String where = EVENTS_WHERE;
253ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            String whereAllday = ALLDAY_WHERE;
254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (hideDeclined) {
255ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                String hideString = " AND " + Instances.SELF_ATTENDEE_STATUS + "!="
256ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                        + Attendees.ATTENDEE_STATUS_DECLINED;
257ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                where += hideString;
258ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                whereAllday += hideString;
259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
261b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            cEvents = instancesQuery(context.getContentResolver(), EVENT_PROJECTION, startDay,
262b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik                    endDay, where, null, SORT_EVENTS_BY);
263b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            cAllday = instancesQuery(context.getContentResolver(), EVENT_PROJECTION, startDay,
264b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik                    endDay, whereAllday, null, SORT_ALLDAY_BY);
265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Check if we should return early because there are more recent
267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // load requests waiting.
268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (requestId != sequenceNumber.get()) {
269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return;
270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
272ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            buildEventsFromCursor(events, cEvents, context, startDay, endDay);
273ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            buildEventsFromCursor(events, cAllday, context, startDay, endDay);
274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } finally {
276ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            if (cEvents != null) {
277ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                cEvents.close();
278ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            }
279ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            if (cAllday != null) {
280ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                cAllday.close();
281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (PROFILE) {
283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                Debug.stopMethodTracing();
284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
288ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    /**
289a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * Performs a query to return all visible instances in the given range
290a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * that match the given selection. This is a blocking function and
291a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * should not be done on the UI thread. This will cause an expansion of
292a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * recurring events to fill this time range if they are not already
293a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * expanded and will slow down for larger time ranges with many
294a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * recurring events.
295a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     *
296a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param cr The ContentResolver to use for the query
297a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param projection The columns to return
298a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param begin The start of the time range to query in UTC millis since
299a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     *            epoch
300a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param end The end of the time range to query in UTC millis since
301a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     *            epoch
302a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param selection Filter on the query as an SQL WHERE statement
303a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param selectionArgs Args to replace any '?'s in the selection
304a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param orderBy How to order the rows as an SQL ORDER BY statement
305a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @return A Cursor of instances matching the selection
306a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     */
307b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik    private static final Cursor instancesQuery(ContentResolver cr, String[] projection,
308b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            int startDay, int endDay, String selection, String[] selectionArgs, String orderBy) {
309a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        String WHERE_CALENDARS_SELECTED = Calendars.VISIBLE + "=?";
310a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        String[] WHERE_CALENDARS_ARGS = {"1"};
311a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        String DEFAULT_SORT_ORDER = "begin ASC";
312a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik
313b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik        Uri.Builder builder = Instances.CONTENT_BY_DAY_URI.buildUpon();
314b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik        ContentUris.appendId(builder, startDay);
315b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik        ContentUris.appendId(builder, endDay);
316a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        if (TextUtils.isEmpty(selection)) {
317a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            selection = WHERE_CALENDARS_SELECTED;
318a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            selectionArgs = WHERE_CALENDARS_ARGS;
319a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        } else {
320a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            selection = "(" + selection + ") AND " + WHERE_CALENDARS_SELECTED;
321a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            if (selectionArgs != null && selectionArgs.length > 0) {
322a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                selectionArgs = Arrays.copyOf(selectionArgs, selectionArgs.length + 1);
323a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                selectionArgs[selectionArgs.length - 1] = WHERE_CALENDARS_ARGS[0];
324a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            } else {
325a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                selectionArgs = WHERE_CALENDARS_ARGS;
326a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            }
327a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        }
328a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        return cr.query(builder.build(), projection, selection, selectionArgs,
329a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
330a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik    }
331a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik
332a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik    /**
333ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * Adds all the events from the cursors to the events list.
334ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     *
335ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param events The list of events
336ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param cEvents Events to add to the list
337ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param context
338ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param startDay
339ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param endDay
340ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     */
341ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    public static void buildEventsFromCursor(
342ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            ArrayList<Event> events, Cursor cEvents, Context context, int startDay, int endDay) {
343ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (cEvents == null || events == null) {
344981874e61ecf29a96a77601a3172b2503b6537eeErik            Log.e(TAG, "buildEventsFromCursor: null cursor or null events list!");
345981874e61ecf29a96a77601a3172b2503b6537eeErik            return;
346981874e61ecf29a96a77601a3172b2503b6537eeErik        }
347981874e61ecf29a96a77601a3172b2503b6537eeErik
348ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        int count = cEvents.getCount();
349981874e61ecf29a96a77601a3172b2503b6537eeErik
350981874e61ecf29a96a77601a3172b2503b6537eeErik        if (count == 0) {
351981874e61ecf29a96a77601a3172b2503b6537eeErik            return;
352981874e61ecf29a96a77601a3172b2503b6537eeErik        }
353981874e61ecf29a96a77601a3172b2503b6537eeErik
354981874e61ecf29a96a77601a3172b2503b6537eeErik        Resources res = context.getResources();
355ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        mNoTitleString = res.getString(R.string.no_title_label);
356ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        mNoColorColor = res.getColor(R.color.event_center);
357ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        // Sort events in two passes so we ensure the allday and standard events
358ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        // get sorted in the correct order
3594d2f035beb502dbd557fe31095c821d23b13608cIsaac Katzenelson        cEvents.moveToPosition(-1);
360ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        while (cEvents.moveToNext()) {
361b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            Event e = generateEventFromCursor(cEvents);
362b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            if (e.startDay > endDay || e.endDay < startDay) {
363b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik                continue;
364b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            }
365ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            events.add(e);
366ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        }
367ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    }
368981874e61ecf29a96a77601a3172b2503b6537eeErik
369ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    /**
370ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param cEvents Cursor pointing at event
371ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @return An event created from the cursor
372ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     */
373b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik    private static Event generateEventFromCursor(Cursor cEvents) {
374ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        Event e = new Event();
375981874e61ecf29a96a77601a3172b2503b6537eeErik
376ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.id = cEvents.getLong(PROJECTION_EVENT_ID_INDEX);
377ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.title = cEvents.getString(PROJECTION_TITLE_INDEX);
378ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.location = cEvents.getString(PROJECTION_LOCATION_INDEX);
379ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.allDay = cEvents.getInt(PROJECTION_ALL_DAY_INDEX) != 0;
380ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.organizer = cEvents.getString(PROJECTION_ORGANIZER_INDEX);
381ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.guestsCanModify = cEvents.getInt(PROJECTION_GUESTS_CAN_INVITE_OTHERS_INDEX) != 0;
382981874e61ecf29a96a77601a3172b2503b6537eeErik
383ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (e.title == null || e.title.length() == 0) {
384ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.title = mNoTitleString;
385ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        }
386981874e61ecf29a96a77601a3172b2503b6537eeErik
387ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (!cEvents.isNull(PROJECTION_COLOR_INDEX)) {
388ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            // Read the color from the database
3894acb2fd087308dea146b8b10f5278c59df387680RoboErik            e.color = Utils.getDisplayColorFromColor(cEvents.getInt(PROJECTION_COLOR_INDEX));
390ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        } else {
391ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.color = mNoColorColor;
392ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        }
393981874e61ecf29a96a77601a3172b2503b6537eeErik
394ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        long eStart = cEvents.getLong(PROJECTION_BEGIN_INDEX);
395ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        long eEnd = cEvents.getLong(PROJECTION_END_INDEX);
396981874e61ecf29a96a77601a3172b2503b6537eeErik
397ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.startMillis = eStart;
398ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.startTime = cEvents.getInt(PROJECTION_START_MINUTE_INDEX);
399ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.startDay = cEvents.getInt(PROJECTION_START_DAY_INDEX);
400981874e61ecf29a96a77601a3172b2503b6537eeErik
401ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.endMillis = eEnd;
402ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.endTime = cEvents.getInt(PROJECTION_END_MINUTE_INDEX);
403ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.endDay = cEvents.getInt(PROJECTION_END_DAY_INDEX);
404981874e61ecf29a96a77601a3172b2503b6537eeErik
405ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.hasAlarm = cEvents.getInt(PROJECTION_HAS_ALARM_INDEX) != 0;
406981874e61ecf29a96a77601a3172b2503b6537eeErik
407ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        // Check if this is a repeating event
408ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        String rrule = cEvents.getString(PROJECTION_RRULE_INDEX);
409ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        String rdate = cEvents.getString(PROJECTION_RDATE_INDEX);
410ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (!TextUtils.isEmpty(rrule) || !TextUtils.isEmpty(rdate)) {
411ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.isRepeating = true;
412ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        } else {
413ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.isRepeating = false;
414981874e61ecf29a96a77601a3172b2503b6537eeErik        }
415ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik
416ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.selfAttendeeStatus = cEvents.getInt(PROJECTION_SELF_ATTENDEE_STATUS_INDEX);
417ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        return e;
418981874e61ecf29a96a77601a3172b2503b6537eeErik    }
419981874e61ecf29a96a77601a3172b2503b6537eeErik
420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Computes a position for each event.  Each event is displayed
422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * as a non-overlapping rectangle.  For normal events, these rectangles
423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * are displayed in separate columns in the week view and day view.  For
424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * all-day events, these rectangles are displayed in separate rows along
425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * the top.  In both cases, each event is assigned two numbers: N, and
426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Max, that specify that this event is the Nth event of Max number of
427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * events that are displayed in a group. The width and position of each
428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * rectangle depend on the maximum number of rectangles that occur at
429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * the same time.
430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param eventsList the list of events, sorted into increasing time order
43246b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa     * @param minimumDurationMillis minimum duration acceptable as cell height of each event
43346b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa     * rectangle in millisecond. Should be 0 when it is not determined.
434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
43546b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa    /* package */ static void computePositions(ArrayList<Event> eventsList,
43627d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa            long minimumDurationMillis) {
43746b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        if (eventsList == null) {
438146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return;
43946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        }
440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // Compute the column positions separately for the all-day events
44246b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        doComputePositions(eventsList, minimumDurationMillis, false);
44346b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        doComputePositions(eventsList, minimumDurationMillis, true);
444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static void doComputePositions(ArrayList<Event> eventsList,
44768655b5af2b7e5f872a103858ec58a19042123ceRoboErik            long minimumDurationMillis, boolean doAlldayEvents) {
44846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        final ArrayList<Event> activeList = new ArrayList<Event>();
44946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        final ArrayList<Event> groupList = new ArrayList<Event>();
45046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa
45127d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa        if (minimumDurationMillis < 0) {
45227d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa            minimumDurationMillis = 0;
45346b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        }
454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long colMask = 0;
456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int maxCols = 0;
457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (Event event : eventsList) {
458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Process all-day events separately
45968655b5af2b7e5f872a103858ec58a19042123ceRoboErik            if (event.drawAsAllday() != doAlldayEvents)
460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                continue;
461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
46268655b5af2b7e5f872a103858ec58a19042123ceRoboErik           if (!doAlldayEvents) {
46368655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask = removeNonAlldayActiveEvents(
46468655b5af2b7e5f872a103858ec58a19042123ceRoboErik                        event, activeList.iterator(), minimumDurationMillis, colMask);
46568655b5af2b7e5f872a103858ec58a19042123ceRoboErik            } else {
46668655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask = removeAlldayActiveEvents(event, activeList.iterator(), colMask);
467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If the active list is empty, then reset the max columns, clear
470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // the column bit mask, and empty the groupList.
471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (activeList.isEmpty()) {
472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                for (Event ev : groupList) {
473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    ev.setMaxColumns(maxCols);
474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                maxCols = 0;
476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                colMask = 0;
477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                groupList.clear();
478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Find the first empty column.  Empty columns are represented by
481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // zero bits in the column mask "colMask".
482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int col = findFirstZeroBit(colMask);
483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (col == 64)
484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                col = 63;
485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            colMask |= (1L << col);
486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            event.setColumn(col);
487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            activeList.add(event);
488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            groupList.add(event);
489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int len = activeList.size();
490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (maxCols < len)
491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                maxCols = len;
492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (Event ev : groupList) {
494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            ev.setMaxColumns(maxCols);
495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
49868655b5af2b7e5f872a103858ec58a19042123ceRoboErik    private static long removeAlldayActiveEvents(Event event, Iterator<Event> iter, long colMask) {
49968655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // Remove the inactive allday events. An event on the active list
50068655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // becomes inactive when the end day is less than the current event's
50168655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // start day.
50268655b5af2b7e5f872a103858ec58a19042123ceRoboErik        while (iter.hasNext()) {
50368655b5af2b7e5f872a103858ec58a19042123ceRoboErik            final Event active = iter.next();
50468655b5af2b7e5f872a103858ec58a19042123ceRoboErik            if (active.endDay < event.startDay) {
50568655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask &= ~(1L << active.getColumn());
50668655b5af2b7e5f872a103858ec58a19042123ceRoboErik                iter.remove();
50768655b5af2b7e5f872a103858ec58a19042123ceRoboErik            }
50868655b5af2b7e5f872a103858ec58a19042123ceRoboErik        }
50968655b5af2b7e5f872a103858ec58a19042123ceRoboErik        return colMask;
51068655b5af2b7e5f872a103858ec58a19042123ceRoboErik    }
51168655b5af2b7e5f872a103858ec58a19042123ceRoboErik
51268655b5af2b7e5f872a103858ec58a19042123ceRoboErik    private static long removeNonAlldayActiveEvents(
51368655b5af2b7e5f872a103858ec58a19042123ceRoboErik            Event event, Iterator<Event> iter, long minDurationMillis, long colMask) {
51468655b5af2b7e5f872a103858ec58a19042123ceRoboErik        long start = event.getStartMillis();
51568655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // Remove the inactive events. An event on the active list
51668655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // becomes inactive when its end time is less than or equal to
51768655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // the current event's start time.
51868655b5af2b7e5f872a103858ec58a19042123ceRoboErik        while (iter.hasNext()) {
51968655b5af2b7e5f872a103858ec58a19042123ceRoboErik            final Event active = iter.next();
52068655b5af2b7e5f872a103858ec58a19042123ceRoboErik
52168655b5af2b7e5f872a103858ec58a19042123ceRoboErik            final long duration = Math.max(
52268655b5af2b7e5f872a103858ec58a19042123ceRoboErik                    active.getEndMillis() - active.getStartMillis(), minDurationMillis);
52368655b5af2b7e5f872a103858ec58a19042123ceRoboErik            if ((active.getStartMillis() + duration) <= start) {
52468655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask &= ~(1L << active.getColumn());
52568655b5af2b7e5f872a103858ec58a19042123ceRoboErik                iter.remove();
52668655b5af2b7e5f872a103858ec58a19042123ceRoboErik            }
52768655b5af2b7e5f872a103858ec58a19042123ceRoboErik        }
52868655b5af2b7e5f872a103858ec58a19042123ceRoboErik        return colMask;
52968655b5af2b7e5f872a103858ec58a19042123ceRoboErik    }
53068655b5af2b7e5f872a103858ec58a19042123ceRoboErik
531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static int findFirstZeroBit(long val) {
532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int ii = 0; ii < 64; ++ii) {
533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if ((val & (1L << ii)) == 0)
534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return ii;
535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return 64;
537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public final void dump() {
540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+-----------------------------------------+");
541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+        id = " + id);
542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+     color = " + color);
543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+     title = " + title);
544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+  location = " + location);
545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+    allDay = " + allDay);
546146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+  startDay = " + startDay);
547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+    endDay = " + endDay);
548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+ startTime = " + startTime);
549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+   endTime = " + endTime);
5506d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        Log.e("Cal", "+ organizer = " + organizer);
5516d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        Log.e("Cal", "+  guestwrt = " + guestsCanModify);
552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public final boolean intersects(int julianDay, int startMinute,
555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int endMinute) {
556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (endDay < julianDay) {
557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return false;
558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (startDay > julianDay) {
561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return false;
562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (endDay == julianDay) {
565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endTime < startMinute) {
566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return false;
567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // An event that ends at the start minute should not be considered
569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // as intersecting the given time span, but don't exclude
570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // zero-length (or very short) events.
571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endTime == startMinute
572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    && (startTime != endTime || startDay != endDay)) {
573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return false;
574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (startDay == julianDay && startTime > endMinute) {
578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return false;
579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return true;
582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Returns the event title and location separated by a comma.  If the
586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * location is already part of the title (at the end of the title), then
587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * just the title is returned.
588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the event title and location as a String
590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public String getTitleAndLocation() {
592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        String text = title.toString();
593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // Append the location to the title, unless the title ends with the
595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // location (for example, "meeting in building 42" ends with the
596146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // location).
597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (location != null) {
598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            String locationString = location.toString();
599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (!text.endsWith(locationString)) {
600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                text += ", " + locationString;
601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return text;
604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setColumn(int column) {
607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mColumn = column;
608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getColumn() {
611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mColumn;
612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setMaxColumns(int maxColumns) {
615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mMaxColumns = maxColumns;
616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getMaxColumns() {
619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mMaxColumns;
620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setStartMillis(long startMillis) {
623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        this.startMillis = startMillis;
624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getStartMillis() {
627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return startMillis;
628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setEndMillis(long endMillis) {
631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        this.endMillis = endMillis;
632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getEndMillis() {
635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return endMillis;
636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
637d031419da7900dab91ac9f512374d7e59bb74dceErik
63868655b5af2b7e5f872a103858ec58a19042123ceRoboErik    public boolean drawAsAllday() {
6391d92cbdf5b754f9da92303eaf554d8db7d7b0849RoboErik        // Use >= so we'll pick up Exchange allday events
6401d92cbdf5b754f9da92303eaf554d8db7d7b0849RoboErik        return allDay || endMillis - startMillis >= DateUtils.DAY_IN_MILLIS;
641d031419da7900dab91ac9f512374d7e59bb74dceErik    }
642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
643