Event.java revision 4acb2fd087308dea146b8b10f5278c59df387680
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;
2525996100d6ea61888ebe54d7708a9a371bb12a55RoboErikimport android.graphics.Color;
26a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport android.net.Uri;
27146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.os.Debug;
28a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport android.provider.CalendarContract;
29a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees;
30a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport android.provider.CalendarContract.Calendars;
31a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Events;
32a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Instances;
33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.TextUtils;
34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateUtils;
35146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time;
36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.util.Log;
37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
38146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.ArrayList;
39a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport java.util.Arrays;
40146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Iterator;
41146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.concurrent.atomic.AtomicInteger;
42146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project// TODO: should Event be Parcelable so it can be passed via Intents?
441d92cbdf5b754f9da92303eaf554d8db7d7b0849RoboErikpublic class Event implements Cloneable {
45146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
46981874e61ecf29a96a77601a3172b2503b6537eeErik    private static final String TAG = "CalEvent";
47146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final boolean PROFILE = false;
48146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
492fda24534978f55711526dbde747aa50d68dec40RoboErik    /**
502fda24534978f55711526dbde747aa50d68dec40RoboErik     * The sort order is:
51ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * 1) events with an earlier start (begin for normal events, startday for allday)
52ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * 2) events with a later end (end for normal events, endday for allday)
53ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * 3) the title (unnecessary, but nice)
542fda24534978f55711526dbde747aa50d68dec40RoboErik     *
552fda24534978f55711526dbde747aa50d68dec40RoboErik     * The start and end day is sorted first so that all day events are
562fda24534978f55711526dbde747aa50d68dec40RoboErik     * sorted correctly with respect to events that are >24 hours (and
572fda24534978f55711526dbde747aa50d68dec40RoboErik     * therefore show up in the allday area).
582fda24534978f55711526dbde747aa50d68dec40RoboErik     */
592fda24534978f55711526dbde747aa50d68dec40RoboErik    private static final String SORT_EVENTS_BY =
60ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            "begin ASC, end DESC, title ASC";
61ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static final String SORT_ALLDAY_BY =
62ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            "startDay ASC, endDay DESC, title ASC";
63ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static final String DISPLAY_AS_ALLDAY = "dispAllday";
64ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik
65ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static final String EVENTS_WHERE = DISPLAY_AS_ALLDAY + "=0";
66ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static final String ALLDAY_WHERE = DISPLAY_AS_ALLDAY + "=1";
672fda24534978f55711526dbde747aa50d68dec40RoboErik
68981874e61ecf29a96a77601a3172b2503b6537eeErik    // The projection to use when querying instances to build a list of events
69981874e61ecf29a96a77601a3172b2503b6537eeErik    public static final String[] EVENT_PROJECTION = new String[] {
70146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.TITLE,                 // 0
71146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.EVENT_LOCATION,        // 1
72146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.ALL_DAY,               // 2
730e1e62408b96e1532eb6f6a609ae4c817751aaf3RoboErik            Instances.CALENDAR_COLOR,        // 3
74146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.EVENT_TIMEZONE,        // 4
75146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.EVENT_ID,              // 5
76146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.BEGIN,                 // 6
77146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.END,                   // 7
78146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances._ID,                   // 8
79146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.START_DAY,             // 9
80146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.END_DAY,               // 10
81146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.START_MINUTE,          // 11
82146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.END_MINUTE,            // 12
83146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.HAS_ALARM,             // 13
84146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.RRULE,                 // 14
85146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.RDATE,                 // 15
86146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Instances.SELF_ATTENDEE_STATUS,  // 16
876d34cec523930368976bc8d358d0a6de1da3462cMichael Chan            Events.ORGANIZER,                // 17
886d34cec523930368976bc8d358d0a6de1da3462cMichael Chan            Events.GUESTS_CAN_MODIFY,        // 18
89ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            Instances.ALL_DAY + "=1 OR (" + Instances.END + "-" + Instances.BEGIN + ")>="
90ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                    + DateUtils.DAY_IN_MILLIS + " AS " + DISPLAY_AS_ALLDAY, // 19
91146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    };
92146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
93146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // The indices for the projection array above.
94146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_TITLE_INDEX = 0;
95146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_LOCATION_INDEX = 1;
96146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_ALL_DAY_INDEX = 2;
97146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_COLOR_INDEX = 3;
98146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_TIMEZONE_INDEX = 4;
99146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_EVENT_ID_INDEX = 5;
100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_BEGIN_INDEX = 6;
101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_END_INDEX = 7;
102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_START_DAY_INDEX = 9;
103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_END_DAY_INDEX = 10;
104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_START_MINUTE_INDEX = 11;
105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_END_MINUTE_INDEX = 12;
106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_HAS_ALARM_INDEX = 13;
107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_RRULE_INDEX = 14;
108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_RDATE_INDEX = 15;
109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int PROJECTION_SELF_ATTENDEE_STATUS_INDEX = 16;
1106d34cec523930368976bc8d358d0a6de1da3462cMichael Chan    private static final int PROJECTION_ORGANIZER_INDEX = 17;
1116d34cec523930368976bc8d358d0a6de1da3462cMichael Chan    private static final int PROJECTION_GUESTS_CAN_INVITE_OTHERS_INDEX = 18;
112ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static final int PROJECTION_DISPLAY_AS_ALLDAY = 19;
113ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik
114ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static String mNoTitleString;
115ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static int mNoColorColor;
116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long id;
118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int color;
119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public CharSequence title;
120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public CharSequence location;
121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean allDay;
1226d34cec523930368976bc8d358d0a6de1da3462cMichael Chan    public String organizer;
1236d34cec523930368976bc8d358d0a6de1da3462cMichael Chan    public boolean guestsCanModify;
124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int startDay;       // start Julian day
126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int endDay;         // end Julian day
127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int startTime;      // Start and end time are in minutes since midnight
128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int endTime;
129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long startMillis;   // UTC milliseconds since the epoch
131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long endMillis;     // UTC milliseconds since the epoch
132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mColumn;
133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mMaxColumns;
134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean hasAlarm;
136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean isRepeating;
137981874e61ecf29a96a77601a3172b2503b6537eeErik
138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int selfAttendeeStatus;
139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // The coordinates of the event rectangle drawn on the screen.
141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float left;
142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float right;
143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float top;
144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float bottom;
145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // These 4 fields are used for navigating among events within the selected
147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // hour in the Day and Week view.
148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextRight;
149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextLeft;
150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextUp;
151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextDown;
152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
15498ab9de2fa5ad8dfd37faa6593dc66fa426d8960Michael Chan    public final Object clone() throws CloneNotSupportedException {
15598ab9de2fa5ad8dfd37faa6593dc66fa426d8960Michael Chan        super.clone();
156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Event e = new Event();
157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.title = title;
159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.color = color;
160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.location = location;
161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.allDay = allDay;
162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startDay = startDay;
163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endDay = endDay;
164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startTime = startTime;
165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endTime = endTime;
166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startMillis = startMillis;
167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endMillis = endMillis;
168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.hasAlarm = hasAlarm;
169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.isRepeating = isRepeating;
170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.selfAttendeeStatus = selfAttendeeStatus;
1716d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        e.organizer = organizer;
1726d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        e.guestsCanModify = guestsCanModify;
173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return e;
175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public final void copyTo(Event dest) {
178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.id = id;
179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.title = title;
180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.color = color;
181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.location = location;
182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.allDay = allDay;
183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.startDay = startDay;
184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.endDay = endDay;
185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.startTime = startTime;
186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.endTime = endTime;
187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.startMillis = startMillis;
188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.endMillis = endMillis;
189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.hasAlarm = hasAlarm;
190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.isRepeating = isRepeating;
191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.selfAttendeeStatus = selfAttendeeStatus;
1926d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        dest.organizer = organizer;
1936d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        dest.guestsCanModify = guestsCanModify;
194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final Event newInstance() {
197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Event e = new Event();
198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.id = 0;
200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.title = null;
201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.color = 0;
202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.location = null;
203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.allDay = false;
204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startDay = 0;
205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endDay = 0;
206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startTime = 0;
207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endTime = 0;
208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startMillis = 0;
209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endMillis = 0;
210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.hasAlarm = false;
211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.isRepeating = false;
212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.selfAttendeeStatus = Attendees.ATTENDEE_STATUS_NONE;
213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return e;
215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
218b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik     * Loads <i>days</i> days worth of instances starting at <i>startDay</i>.
219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
220b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik    public static void loadEvents(Context context, ArrayList<Event> events, int startDay, int days,
221b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            int requestId, AtomicInteger sequenceNumber) {
222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (PROFILE) {
224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Debug.startMethodTracing("loadEvents");
225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
227ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        Cursor cEvents = null;
228ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        Cursor cAllday = null;
229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        events.clear();
231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        try {
232b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            int endDay = startDay + days - 1;
233b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik
234b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            // We use the byDay instances query to get a list of all events for
235b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            // the days we're interested in.
236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // The sort order is: events with an earlier start time occur
237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // first and if the start times are the same, then events with
238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // a later end time occur first. The later end time is ordered
239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // first so that long rectangles in the calendar views appear on
240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // the left side.  If the start and end times of two events are
241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // the same then we sort alphabetically on the title.  This isn't
242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // required for correctness, it just adds a nice touch.
243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Respect the preference to show/hide declined events
2454b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa            SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
2464b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa            boolean hideDeclined = prefs.getBoolean(GeneralPreferences.KEY_HIDE_DECLINED,
247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    false);
248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
249ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            String where = EVENTS_WHERE;
250ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            String whereAllday = ALLDAY_WHERE;
251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (hideDeclined) {
252ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                String hideString = " AND " + Instances.SELF_ATTENDEE_STATUS + "!="
253ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                        + Attendees.ATTENDEE_STATUS_DECLINED;
254ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                where += hideString;
255ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                whereAllday += hideString;
256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
258b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            cEvents = instancesQuery(context.getContentResolver(), EVENT_PROJECTION, startDay,
259b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik                    endDay, where, null, SORT_EVENTS_BY);
260b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            cAllday = instancesQuery(context.getContentResolver(), EVENT_PROJECTION, startDay,
261b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik                    endDay, whereAllday, null, SORT_ALLDAY_BY);
262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Check if we should return early because there are more recent
264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // load requests waiting.
265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (requestId != sequenceNumber.get()) {
266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return;
267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
269ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            buildEventsFromCursor(events, cEvents, context, startDay, endDay);
270ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            buildEventsFromCursor(events, cAllday, context, startDay, endDay);
271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } finally {
273ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            if (cEvents != null) {
274ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                cEvents.close();
275ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            }
276ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            if (cAllday != null) {
277ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                cAllday.close();
278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (PROFILE) {
280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                Debug.stopMethodTracing();
281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
285ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    /**
286a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * Performs a query to return all visible instances in the given range
287a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * that match the given selection. This is a blocking function and
288a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * should not be done on the UI thread. This will cause an expansion of
289a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * recurring events to fill this time range if they are not already
290a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * expanded and will slow down for larger time ranges with many
291a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * recurring events.
292a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     *
293a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param cr The ContentResolver to use for the query
294a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param projection The columns to return
295a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param begin The start of the time range to query in UTC millis since
296a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     *            epoch
297a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param end The end of the time range to query in UTC millis since
298a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     *            epoch
299a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param selection Filter on the query as an SQL WHERE statement
300a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param selectionArgs Args to replace any '?'s in the selection
301a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param orderBy How to order the rows as an SQL ORDER BY statement
302a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @return A Cursor of instances matching the selection
303a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     */
304b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik    private static final Cursor instancesQuery(ContentResolver cr, String[] projection,
305b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            int startDay, int endDay, String selection, String[] selectionArgs, String orderBy) {
306a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        String WHERE_CALENDARS_SELECTED = Calendars.VISIBLE + "=?";
307a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        String[] WHERE_CALENDARS_ARGS = {"1"};
308a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        String DEFAULT_SORT_ORDER = "begin ASC";
309a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik
310b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik        Uri.Builder builder = Instances.CONTENT_BY_DAY_URI.buildUpon();
311b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik        ContentUris.appendId(builder, startDay);
312b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik        ContentUris.appendId(builder, endDay);
313a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        if (TextUtils.isEmpty(selection)) {
314a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            selection = WHERE_CALENDARS_SELECTED;
315a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            selectionArgs = WHERE_CALENDARS_ARGS;
316a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        } else {
317a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            selection = "(" + selection + ") AND " + WHERE_CALENDARS_SELECTED;
318a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            if (selectionArgs != null && selectionArgs.length > 0) {
319a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                selectionArgs = Arrays.copyOf(selectionArgs, selectionArgs.length + 1);
320a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                selectionArgs[selectionArgs.length - 1] = WHERE_CALENDARS_ARGS[0];
321a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            } else {
322a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                selectionArgs = WHERE_CALENDARS_ARGS;
323a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            }
324a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        }
325a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        return cr.query(builder.build(), projection, selection, selectionArgs,
326a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
327a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik    }
328a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik
329a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik    /**
330ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * Adds all the events from the cursors to the events list.
331ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     *
332ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param events The list of events
333ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param cEvents Events to add to the list
334ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param context
335ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param startDay
336ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param endDay
337ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     */
338ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    public static void buildEventsFromCursor(
339ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            ArrayList<Event> events, Cursor cEvents, Context context, int startDay, int endDay) {
340ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (cEvents == null || events == null) {
341981874e61ecf29a96a77601a3172b2503b6537eeErik            Log.e(TAG, "buildEventsFromCursor: null cursor or null events list!");
342981874e61ecf29a96a77601a3172b2503b6537eeErik            return;
343981874e61ecf29a96a77601a3172b2503b6537eeErik        }
344981874e61ecf29a96a77601a3172b2503b6537eeErik
345ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        int count = cEvents.getCount();
346981874e61ecf29a96a77601a3172b2503b6537eeErik
347981874e61ecf29a96a77601a3172b2503b6537eeErik        if (count == 0) {
348981874e61ecf29a96a77601a3172b2503b6537eeErik            return;
349981874e61ecf29a96a77601a3172b2503b6537eeErik        }
350981874e61ecf29a96a77601a3172b2503b6537eeErik
351981874e61ecf29a96a77601a3172b2503b6537eeErik        Resources res = context.getResources();
352ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        mNoTitleString = res.getString(R.string.no_title_label);
353ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        mNoColorColor = res.getColor(R.color.event_center);
354ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        // Sort events in two passes so we ensure the allday and standard events
355ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        // get sorted in the correct order
356ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        while (cEvents.moveToNext()) {
357b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            Event e = generateEventFromCursor(cEvents);
358b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            if (e.startDay > endDay || e.endDay < startDay) {
359b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik                continue;
360b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            }
361ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            events.add(e);
362ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        }
363ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    }
364981874e61ecf29a96a77601a3172b2503b6537eeErik
365ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    /**
366ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param cEvents Cursor pointing at event
367ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @return An event created from the cursor
368ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     */
369b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik    private static Event generateEventFromCursor(Cursor cEvents) {
370ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        Event e = new Event();
371981874e61ecf29a96a77601a3172b2503b6537eeErik
372ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.id = cEvents.getLong(PROJECTION_EVENT_ID_INDEX);
373ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.title = cEvents.getString(PROJECTION_TITLE_INDEX);
374ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.location = cEvents.getString(PROJECTION_LOCATION_INDEX);
375ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.allDay = cEvents.getInt(PROJECTION_ALL_DAY_INDEX) != 0;
376ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.organizer = cEvents.getString(PROJECTION_ORGANIZER_INDEX);
377ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.guestsCanModify = cEvents.getInt(PROJECTION_GUESTS_CAN_INVITE_OTHERS_INDEX) != 0;
378981874e61ecf29a96a77601a3172b2503b6537eeErik
379ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (e.title == null || e.title.length() == 0) {
380ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.title = mNoTitleString;
381ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        }
382981874e61ecf29a96a77601a3172b2503b6537eeErik
383ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (!cEvents.isNull(PROJECTION_COLOR_INDEX)) {
384ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            // Read the color from the database
3854acb2fd087308dea146b8b10f5278c59df387680RoboErik            e.color = Utils.getDisplayColorFromColor(cEvents.getInt(PROJECTION_COLOR_INDEX));
386ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        } else {
387ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.color = mNoColorColor;
388ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        }
389981874e61ecf29a96a77601a3172b2503b6537eeErik
390ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        long eStart = cEvents.getLong(PROJECTION_BEGIN_INDEX);
391ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        long eEnd = cEvents.getLong(PROJECTION_END_INDEX);
392981874e61ecf29a96a77601a3172b2503b6537eeErik
393ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.startMillis = eStart;
394ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.startTime = cEvents.getInt(PROJECTION_START_MINUTE_INDEX);
395ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.startDay = cEvents.getInt(PROJECTION_START_DAY_INDEX);
396981874e61ecf29a96a77601a3172b2503b6537eeErik
397ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.endMillis = eEnd;
398ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.endTime = cEvents.getInt(PROJECTION_END_MINUTE_INDEX);
399ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.endDay = cEvents.getInt(PROJECTION_END_DAY_INDEX);
400981874e61ecf29a96a77601a3172b2503b6537eeErik
401ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.hasAlarm = cEvents.getInt(PROJECTION_HAS_ALARM_INDEX) != 0;
402981874e61ecf29a96a77601a3172b2503b6537eeErik
403ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        // Check if this is a repeating event
404ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        String rrule = cEvents.getString(PROJECTION_RRULE_INDEX);
405ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        String rdate = cEvents.getString(PROJECTION_RDATE_INDEX);
406ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (!TextUtils.isEmpty(rrule) || !TextUtils.isEmpty(rdate)) {
407ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.isRepeating = true;
408ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        } else {
409ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.isRepeating = false;
410981874e61ecf29a96a77601a3172b2503b6537eeErik        }
411ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik
412ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.selfAttendeeStatus = cEvents.getInt(PROJECTION_SELF_ATTENDEE_STATUS_INDEX);
413ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        return e;
414981874e61ecf29a96a77601a3172b2503b6537eeErik    }
415981874e61ecf29a96a77601a3172b2503b6537eeErik
416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Computes a position for each event.  Each event is displayed
418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * as a non-overlapping rectangle.  For normal events, these rectangles
419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * are displayed in separate columns in the week view and day view.  For
420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * all-day events, these rectangles are displayed in separate rows along
421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * the top.  In both cases, each event is assigned two numbers: N, and
422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Max, that specify that this event is the Nth event of Max number of
423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * events that are displayed in a group. The width and position of each
424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * rectangle depend on the maximum number of rectangles that occur at
425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * the same time.
426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param eventsList the list of events, sorted into increasing time order
42846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa     * @param minimumDurationMillis minimum duration acceptable as cell height of each event
42946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa     * rectangle in millisecond. Should be 0 when it is not determined.
430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
43146b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa    /* package */ static void computePositions(ArrayList<Event> eventsList,
43227d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa            long minimumDurationMillis) {
43346b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        if (eventsList == null) {
434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return;
43546b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        }
436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // Compute the column positions separately for the all-day events
43846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        doComputePositions(eventsList, minimumDurationMillis, false);
43946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        doComputePositions(eventsList, minimumDurationMillis, true);
440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static void doComputePositions(ArrayList<Event> eventsList,
44368655b5af2b7e5f872a103858ec58a19042123ceRoboErik            long minimumDurationMillis, boolean doAlldayEvents) {
44446b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        final ArrayList<Event> activeList = new ArrayList<Event>();
44546b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        final ArrayList<Event> groupList = new ArrayList<Event>();
44646b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa
44727d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa        if (minimumDurationMillis < 0) {
44827d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa            minimumDurationMillis = 0;
44946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        }
450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long colMask = 0;
452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int maxCols = 0;
453146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (Event event : eventsList) {
454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Process all-day events separately
45568655b5af2b7e5f872a103858ec58a19042123ceRoboErik            if (event.drawAsAllday() != doAlldayEvents)
456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                continue;
457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
45868655b5af2b7e5f872a103858ec58a19042123ceRoboErik           if (!doAlldayEvents) {
45968655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask = removeNonAlldayActiveEvents(
46068655b5af2b7e5f872a103858ec58a19042123ceRoboErik                        event, activeList.iterator(), minimumDurationMillis, colMask);
46168655b5af2b7e5f872a103858ec58a19042123ceRoboErik            } else {
46268655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask = removeAlldayActiveEvents(event, activeList.iterator(), colMask);
463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If the active list is empty, then reset the max columns, clear
466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // the column bit mask, and empty the groupList.
467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (activeList.isEmpty()) {
468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                for (Event ev : groupList) {
469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    ev.setMaxColumns(maxCols);
470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                maxCols = 0;
472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                colMask = 0;
473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                groupList.clear();
474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Find the first empty column.  Empty columns are represented by
477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // zero bits in the column mask "colMask".
478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int col = findFirstZeroBit(colMask);
479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (col == 64)
480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                col = 63;
481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            colMask |= (1L << col);
482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            event.setColumn(col);
483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            activeList.add(event);
484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            groupList.add(event);
485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int len = activeList.size();
486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (maxCols < len)
487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                maxCols = len;
488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (Event ev : groupList) {
490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            ev.setMaxColumns(maxCols);
491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
49468655b5af2b7e5f872a103858ec58a19042123ceRoboErik    private static long removeAlldayActiveEvents(Event event, Iterator<Event> iter, long colMask) {
49568655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // Remove the inactive allday events. An event on the active list
49668655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // becomes inactive when the end day is less than the current event's
49768655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // start day.
49868655b5af2b7e5f872a103858ec58a19042123ceRoboErik        while (iter.hasNext()) {
49968655b5af2b7e5f872a103858ec58a19042123ceRoboErik            final Event active = iter.next();
50068655b5af2b7e5f872a103858ec58a19042123ceRoboErik            if (active.endDay < event.startDay) {
50168655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask &= ~(1L << active.getColumn());
50268655b5af2b7e5f872a103858ec58a19042123ceRoboErik                iter.remove();
50368655b5af2b7e5f872a103858ec58a19042123ceRoboErik            }
50468655b5af2b7e5f872a103858ec58a19042123ceRoboErik        }
50568655b5af2b7e5f872a103858ec58a19042123ceRoboErik        return colMask;
50668655b5af2b7e5f872a103858ec58a19042123ceRoboErik    }
50768655b5af2b7e5f872a103858ec58a19042123ceRoboErik
50868655b5af2b7e5f872a103858ec58a19042123ceRoboErik    private static long removeNonAlldayActiveEvents(
50968655b5af2b7e5f872a103858ec58a19042123ceRoboErik            Event event, Iterator<Event> iter, long minDurationMillis, long colMask) {
51068655b5af2b7e5f872a103858ec58a19042123ceRoboErik        long start = event.getStartMillis();
51168655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // Remove the inactive events. An event on the active list
51268655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // becomes inactive when its end time is less than or equal to
51368655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // the current event's start time.
51468655b5af2b7e5f872a103858ec58a19042123ceRoboErik        while (iter.hasNext()) {
51568655b5af2b7e5f872a103858ec58a19042123ceRoboErik            final Event active = iter.next();
51668655b5af2b7e5f872a103858ec58a19042123ceRoboErik
51768655b5af2b7e5f872a103858ec58a19042123ceRoboErik            final long duration = Math.max(
51868655b5af2b7e5f872a103858ec58a19042123ceRoboErik                    active.getEndMillis() - active.getStartMillis(), minDurationMillis);
51968655b5af2b7e5f872a103858ec58a19042123ceRoboErik            if ((active.getStartMillis() + duration) <= start) {
52068655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask &= ~(1L << active.getColumn());
52168655b5af2b7e5f872a103858ec58a19042123ceRoboErik                iter.remove();
52268655b5af2b7e5f872a103858ec58a19042123ceRoboErik            }
52368655b5af2b7e5f872a103858ec58a19042123ceRoboErik        }
52468655b5af2b7e5f872a103858ec58a19042123ceRoboErik        return colMask;
52568655b5af2b7e5f872a103858ec58a19042123ceRoboErik    }
52668655b5af2b7e5f872a103858ec58a19042123ceRoboErik
527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static int findFirstZeroBit(long val) {
528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int ii = 0; ii < 64; ++ii) {
529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if ((val & (1L << ii)) == 0)
530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return ii;
531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return 64;
533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public final void dump() {
536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+-----------------------------------------+");
537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+        id = " + id);
538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+     color = " + color);
539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+     title = " + title);
540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+  location = " + location);
541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+    allDay = " + allDay);
542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+  startDay = " + startDay);
543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+    endDay = " + endDay);
544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+ startTime = " + startTime);
545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+   endTime = " + endTime);
5466d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        Log.e("Cal", "+ organizer = " + organizer);
5476d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        Log.e("Cal", "+  guestwrt = " + guestsCanModify);
548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public final boolean intersects(int julianDay, int startMinute,
551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int endMinute) {
552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (endDay < julianDay) {
553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return false;
554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (startDay > julianDay) {
557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return false;
558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (endDay == julianDay) {
561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endTime < startMinute) {
562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return false;
563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // An event that ends at the start minute should not be considered
565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // as intersecting the given time span, but don't exclude
566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // zero-length (or very short) events.
567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endTime == startMinute
568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    && (startTime != endTime || startDay != endDay)) {
569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return false;
570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (startDay == julianDay && startTime > endMinute) {
574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return false;
575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return true;
578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Returns the event title and location separated by a comma.  If the
582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * location is already part of the title (at the end of the title), then
583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * just the title is returned.
584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the event title and location as a String
586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public String getTitleAndLocation() {
588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        String text = title.toString();
589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // Append the location to the title, unless the title ends with the
591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // location (for example, "meeting in building 42" ends with the
592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // location).
593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (location != null) {
594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            String locationString = location.toString();
595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (!text.endsWith(locationString)) {
596146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                text += ", " + locationString;
597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return text;
600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setColumn(int column) {
603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mColumn = column;
604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getColumn() {
607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mColumn;
608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setMaxColumns(int maxColumns) {
611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mMaxColumns = maxColumns;
612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getMaxColumns() {
615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mMaxColumns;
616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setStartMillis(long startMillis) {
619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        this.startMillis = startMillis;
620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getStartMillis() {
623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return startMillis;
624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setEndMillis(long endMillis) {
627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        this.endMillis = endMillis;
628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getEndMillis() {
631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return endMillis;
632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
633d031419da7900dab91ac9f512374d7e59bb74dceErik
63468655b5af2b7e5f872a103858ec58a19042123ceRoboErik    public boolean drawAsAllday() {
6351d92cbdf5b754f9da92303eaf554d8db7d7b0849RoboErik        // Use >= so we'll pick up Exchange allday events
6361d92cbdf5b754f9da92303eaf554d8db7d7b0849RoboErik        return allDay || endMillis - startMillis >= DateUtils.DAY_IN_MILLIS;
637d031419da7900dab91ac9f512374d7e59bb74dceErik    }
638146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
639