Event.java revision b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1
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
11425996100d6ea61888ebe54d7708a9a371bb12a55RoboErik    private static final float SATURATION_ADJUST = 0.3f;
115ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static String mNoTitleString;
116ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    private static int mNoColorColor;
117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long id;
119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int color;
120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public CharSequence title;
121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public CharSequence location;
122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean allDay;
1236d34cec523930368976bc8d358d0a6de1da3462cMichael Chan    public String organizer;
1246d34cec523930368976bc8d358d0a6de1da3462cMichael Chan    public boolean guestsCanModify;
125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int startDay;       // start Julian day
127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int endDay;         // end Julian day
128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int startTime;      // Start and end time are in minutes since midnight
129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int endTime;
130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long startMillis;   // UTC milliseconds since the epoch
132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long endMillis;     // UTC milliseconds since the epoch
133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mColumn;
134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mMaxColumns;
135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean hasAlarm;
137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean isRepeating;
138981874e61ecf29a96a77601a3172b2503b6537eeErik
139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int selfAttendeeStatus;
140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // The coordinates of the event rectangle drawn on the screen.
142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float left;
143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float right;
144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float top;
145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public float bottom;
146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // These 4 fields are used for navigating among events within the selected
148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // hour in the Day and Week view.
149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextRight;
150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextLeft;
151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextUp;
152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Event nextDown;
153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
15598ab9de2fa5ad8dfd37faa6593dc66fa426d8960Michael Chan    public final Object clone() throws CloneNotSupportedException {
15698ab9de2fa5ad8dfd37faa6593dc66fa426d8960Michael Chan        super.clone();
157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Event e = new Event();
158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.title = title;
160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.color = color;
161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.location = location;
162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.allDay = allDay;
163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startDay = startDay;
164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endDay = endDay;
165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startTime = startTime;
166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endTime = endTime;
167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startMillis = startMillis;
168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endMillis = endMillis;
169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.hasAlarm = hasAlarm;
170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.isRepeating = isRepeating;
171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.selfAttendeeStatus = selfAttendeeStatus;
1726d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        e.organizer = organizer;
1736d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        e.guestsCanModify = guestsCanModify;
174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return e;
176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public final void copyTo(Event dest) {
179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.id = id;
180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.title = title;
181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.color = color;
182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.location = location;
183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.allDay = allDay;
184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.startDay = startDay;
185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.endDay = endDay;
186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.startTime = startTime;
187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.endTime = endTime;
188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.startMillis = startMillis;
189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.endMillis = endMillis;
190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.hasAlarm = hasAlarm;
191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.isRepeating = isRepeating;
192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        dest.selfAttendeeStatus = selfAttendeeStatus;
1936d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        dest.organizer = organizer;
1946d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        dest.guestsCanModify = guestsCanModify;
195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final Event newInstance() {
198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Event e = new Event();
199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.id = 0;
201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.title = null;
202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.color = 0;
203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.location = null;
204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.allDay = false;
205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startDay = 0;
206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endDay = 0;
207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startTime = 0;
208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endTime = 0;
209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.startMillis = 0;
210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.endMillis = 0;
211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.hasAlarm = false;
212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.isRepeating = false;
213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        e.selfAttendeeStatus = Attendees.ATTENDEE_STATUS_NONE;
214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return e;
216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
219b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik     * Loads <i>days</i> days worth of instances starting at <i>startDay</i>.
220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
221b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik    public static void loadEvents(Context context, ArrayList<Event> events, int startDay, int days,
222b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            int requestId, AtomicInteger sequenceNumber) {
223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (PROFILE) {
225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Debug.startMethodTracing("loadEvents");
226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
228ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        Cursor cEvents = null;
229ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        Cursor cAllday = null;
230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        events.clear();
232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        try {
233b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            int endDay = startDay + days - 1;
234b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik
235b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            // We use the byDay instances query to get a list of all events for
236b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            // the days we're interested in.
237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // The sort order is: events with an earlier start time occur
238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // first and if the start times are the same, then events with
239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // a later end time occur first. The later end time is ordered
240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // first so that long rectangles in the calendar views appear on
241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // the left side.  If the start and end times of two events are
242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // the same then we sort alphabetically on the title.  This isn't
243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // required for correctness, it just adds a nice touch.
244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Respect the preference to show/hide declined events
2464b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa            SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
2474b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa            boolean hideDeclined = prefs.getBoolean(GeneralPreferences.KEY_HIDE_DECLINED,
248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    false);
249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
250ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            String where = EVENTS_WHERE;
251ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            String whereAllday = ALLDAY_WHERE;
252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (hideDeclined) {
253ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                String hideString = " AND " + Instances.SELF_ATTENDEE_STATUS + "!="
254ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                        + Attendees.ATTENDEE_STATUS_DECLINED;
255ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                where += hideString;
256ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                whereAllday += hideString;
257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
259b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            cEvents = instancesQuery(context.getContentResolver(), EVENT_PROJECTION, startDay,
260b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik                    endDay, where, null, SORT_EVENTS_BY);
261b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            cAllday = instancesQuery(context.getContentResolver(), EVENT_PROJECTION, startDay,
262b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik                    endDay, whereAllday, null, SORT_ALLDAY_BY);
263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Check if we should return early because there are more recent
265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // load requests waiting.
266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (requestId != sequenceNumber.get()) {
267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return;
268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
270ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            buildEventsFromCursor(events, cEvents, context, startDay, endDay);
271ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            buildEventsFromCursor(events, cAllday, context, startDay, endDay);
272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } finally {
274ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            if (cEvents != null) {
275ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                cEvents.close();
276ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            }
277ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            if (cAllday != null) {
278ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik                cAllday.close();
279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (PROFILE) {
281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                Debug.stopMethodTracing();
282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
286ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    /**
287a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * Performs a query to return all visible instances in the given range
288a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * that match the given selection. This is a blocking function and
289a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * should not be done on the UI thread. This will cause an expansion of
290a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * recurring events to fill this time range if they are not already
291a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * expanded and will slow down for larger time ranges with many
292a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * recurring events.
293a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     *
294a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param cr The ContentResolver to use for the query
295a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param projection The columns to return
296a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param begin The start of the time range to query in UTC millis since
297a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     *            epoch
298a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param end The end of the time range to query in UTC millis since
299a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     *            epoch
300a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param selection Filter on the query as an SQL WHERE statement
301a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param selectionArgs Args to replace any '?'s in the selection
302a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @param orderBy How to order the rows as an SQL ORDER BY statement
303a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     * @return A Cursor of instances matching the selection
304a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik     */
305b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik    private static final Cursor instancesQuery(ContentResolver cr, String[] projection,
306b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            int startDay, int endDay, String selection, String[] selectionArgs, String orderBy) {
307a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        String WHERE_CALENDARS_SELECTED = Calendars.VISIBLE + "=?";
308a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        String[] WHERE_CALENDARS_ARGS = {"1"};
309a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        String DEFAULT_SORT_ORDER = "begin ASC";
310a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik
311b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik        Uri.Builder builder = Instances.CONTENT_BY_DAY_URI.buildUpon();
312b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik        ContentUris.appendId(builder, startDay);
313b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik        ContentUris.appendId(builder, endDay);
314a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        if (TextUtils.isEmpty(selection)) {
315a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            selection = WHERE_CALENDARS_SELECTED;
316a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            selectionArgs = WHERE_CALENDARS_ARGS;
317a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        } else {
318a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            selection = "(" + selection + ") AND " + WHERE_CALENDARS_SELECTED;
319a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            if (selectionArgs != null && selectionArgs.length > 0) {
320a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                selectionArgs = Arrays.copyOf(selectionArgs, selectionArgs.length + 1);
321a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                selectionArgs[selectionArgs.length - 1] = WHERE_CALENDARS_ARGS[0];
322a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            } else {
323a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                selectionArgs = WHERE_CALENDARS_ARGS;
324a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            }
325a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        }
326a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        return cr.query(builder.build(), projection, selection, selectionArgs,
327a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik                orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
328a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik    }
329a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik
330a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik    /**
331ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * Adds all the events from the cursors to the events list.
332ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     *
333ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param events The list of events
334ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param cEvents Events to add to the list
335ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param context
336ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param startDay
337ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param endDay
338ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     */
339ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    public static void buildEventsFromCursor(
340ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            ArrayList<Event> events, Cursor cEvents, Context context, int startDay, int endDay) {
341ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (cEvents == null || events == null) {
342981874e61ecf29a96a77601a3172b2503b6537eeErik            Log.e(TAG, "buildEventsFromCursor: null cursor or null events list!");
343981874e61ecf29a96a77601a3172b2503b6537eeErik            return;
344981874e61ecf29a96a77601a3172b2503b6537eeErik        }
345981874e61ecf29a96a77601a3172b2503b6537eeErik
346ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        int count = cEvents.getCount();
347981874e61ecf29a96a77601a3172b2503b6537eeErik
348981874e61ecf29a96a77601a3172b2503b6537eeErik        if (count == 0) {
349981874e61ecf29a96a77601a3172b2503b6537eeErik            return;
350981874e61ecf29a96a77601a3172b2503b6537eeErik        }
351981874e61ecf29a96a77601a3172b2503b6537eeErik
352981874e61ecf29a96a77601a3172b2503b6537eeErik        Resources res = context.getResources();
353ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        mNoTitleString = res.getString(R.string.no_title_label);
354ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        mNoColorColor = res.getColor(R.color.event_center);
355ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        // Sort events in two passes so we ensure the allday and standard events
356ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        // get sorted in the correct order
357ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        while (cEvents.moveToNext()) {
358b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            Event e = generateEventFromCursor(cEvents);
359b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            if (e.startDay > endDay || e.endDay < startDay) {
360b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik                continue;
361b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik            }
362ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            events.add(e);
363ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        }
364ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    }
365981874e61ecf29a96a77601a3172b2503b6537eeErik
366ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik    /**
367ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @param cEvents Cursor pointing at event
368ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     * @return An event created from the cursor
369ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik     */
370b5e3c17201b2c08ca9f3fd33f4585e1ec8fa71b1RoboErik    private static Event generateEventFromCursor(Cursor cEvents) {
371ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        Event e = new Event();
372981874e61ecf29a96a77601a3172b2503b6537eeErik
373ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.id = cEvents.getLong(PROJECTION_EVENT_ID_INDEX);
374ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.title = cEvents.getString(PROJECTION_TITLE_INDEX);
375ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.location = cEvents.getString(PROJECTION_LOCATION_INDEX);
376ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.allDay = cEvents.getInt(PROJECTION_ALL_DAY_INDEX) != 0;
377ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.organizer = cEvents.getString(PROJECTION_ORGANIZER_INDEX);
378ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.guestsCanModify = cEvents.getInt(PROJECTION_GUESTS_CAN_INVITE_OTHERS_INDEX) != 0;
379981874e61ecf29a96a77601a3172b2503b6537eeErik
380ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (e.title == null || e.title.length() == 0) {
381ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.title = mNoTitleString;
382ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        }
383981874e61ecf29a96a77601a3172b2503b6537eeErik
384ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (!cEvents.isNull(PROJECTION_COLOR_INDEX)) {
385ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            // Read the color from the database
386ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.color = cEvents.getInt(PROJECTION_COLOR_INDEX);
38725996100d6ea61888ebe54d7708a9a371bb12a55RoboErik            float[] hsv = new float[3];
38825996100d6ea61888ebe54d7708a9a371bb12a55RoboErik            Color.colorToHSV(e.color, hsv);
38925996100d6ea61888ebe54d7708a9a371bb12a55RoboErik            hsv[1] = Math.max(hsv[1] - SATURATION_ADJUST, 0.0f);
39025996100d6ea61888ebe54d7708a9a371bb12a55RoboErik            e.color = Color.HSVToColor(hsv);
391ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        } else {
392ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.color = mNoColorColor;
393ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        }
394981874e61ecf29a96a77601a3172b2503b6537eeErik
395ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        long eStart = cEvents.getLong(PROJECTION_BEGIN_INDEX);
396ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        long eEnd = cEvents.getLong(PROJECTION_END_INDEX);
397981874e61ecf29a96a77601a3172b2503b6537eeErik
398ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.startMillis = eStart;
399ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.startTime = cEvents.getInt(PROJECTION_START_MINUTE_INDEX);
400ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.startDay = cEvents.getInt(PROJECTION_START_DAY_INDEX);
401981874e61ecf29a96a77601a3172b2503b6537eeErik
402ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.endMillis = eEnd;
403ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.endTime = cEvents.getInt(PROJECTION_END_MINUTE_INDEX);
404ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.endDay = cEvents.getInt(PROJECTION_END_DAY_INDEX);
405981874e61ecf29a96a77601a3172b2503b6537eeErik
406ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.hasAlarm = cEvents.getInt(PROJECTION_HAS_ALARM_INDEX) != 0;
407981874e61ecf29a96a77601a3172b2503b6537eeErik
408ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        // Check if this is a repeating event
409ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        String rrule = cEvents.getString(PROJECTION_RRULE_INDEX);
410ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        String rdate = cEvents.getString(PROJECTION_RDATE_INDEX);
411ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        if (!TextUtils.isEmpty(rrule) || !TextUtils.isEmpty(rdate)) {
412ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.isRepeating = true;
413ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        } else {
414ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik            e.isRepeating = false;
415981874e61ecf29a96a77601a3172b2503b6537eeErik        }
416ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik
417ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        e.selfAttendeeStatus = cEvents.getInt(PROJECTION_SELF_ATTENDEE_STATUS_INDEX);
418ff982e820f7c1e5f369ea71bf1e6fc511778bac4RoboErik        return e;
419981874e61ecf29a96a77601a3172b2503b6537eeErik    }
420981874e61ecf29a96a77601a3172b2503b6537eeErik
421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Computes a position for each event.  Each event is displayed
423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * as a non-overlapping rectangle.  For normal events, these rectangles
424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * are displayed in separate columns in the week view and day view.  For
425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * all-day events, these rectangles are displayed in separate rows along
426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * the top.  In both cases, each event is assigned two numbers: N, and
427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Max, that specify that this event is the Nth event of Max number of
428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * events that are displayed in a group. The width and position of each
429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * rectangle depend on the maximum number of rectangles that occur at
430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * the same time.
431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param eventsList the list of events, sorted into increasing time order
43346b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa     * @param minimumDurationMillis minimum duration acceptable as cell height of each event
43446b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa     * rectangle in millisecond. Should be 0 when it is not determined.
435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
43646b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa    /* package */ static void computePositions(ArrayList<Event> eventsList,
43727d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa            long minimumDurationMillis) {
43846b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        if (eventsList == null) {
439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return;
44046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        }
441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // Compute the column positions separately for the all-day events
44346b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        doComputePositions(eventsList, minimumDurationMillis, false);
44446b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        doComputePositions(eventsList, minimumDurationMillis, true);
445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static void doComputePositions(ArrayList<Event> eventsList,
44868655b5af2b7e5f872a103858ec58a19042123ceRoboErik            long minimumDurationMillis, boolean doAlldayEvents) {
44946b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        final ArrayList<Event> activeList = new ArrayList<Event>();
45046b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        final ArrayList<Event> groupList = new ArrayList<Event>();
45146b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa
45227d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa        if (minimumDurationMillis < 0) {
45327d671cdba3e8b50219def2c9e1118abe987f908Daisuke Miyakawa            minimumDurationMillis = 0;
45446b05ffc746a3150b6bad5d3a72138ffa38b0a99Daisuke Miyakawa        }
455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
456146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long colMask = 0;
457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int maxCols = 0;
458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (Event event : eventsList) {
459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Process all-day events separately
46068655b5af2b7e5f872a103858ec58a19042123ceRoboErik            if (event.drawAsAllday() != doAlldayEvents)
461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                continue;
462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
46368655b5af2b7e5f872a103858ec58a19042123ceRoboErik           if (!doAlldayEvents) {
46468655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask = removeNonAlldayActiveEvents(
46568655b5af2b7e5f872a103858ec58a19042123ceRoboErik                        event, activeList.iterator(), minimumDurationMillis, colMask);
46668655b5af2b7e5f872a103858ec58a19042123ceRoboErik            } else {
46768655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask = removeAlldayActiveEvents(event, activeList.iterator(), colMask);
468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If the active list is empty, then reset the max columns, clear
471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // the column bit mask, and empty the groupList.
472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (activeList.isEmpty()) {
473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                for (Event ev : groupList) {
474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    ev.setMaxColumns(maxCols);
475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                maxCols = 0;
477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                colMask = 0;
478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                groupList.clear();
479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
481146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Find the first empty column.  Empty columns are represented by
482146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // zero bits in the column mask "colMask".
483146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int col = findFirstZeroBit(colMask);
484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (col == 64)
485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                col = 63;
486146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            colMask |= (1L << col);
487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            event.setColumn(col);
488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            activeList.add(event);
489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            groupList.add(event);
490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int len = activeList.size();
491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (maxCols < len)
492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                maxCols = len;
493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (Event ev : groupList) {
495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            ev.setMaxColumns(maxCols);
496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
498146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
49968655b5af2b7e5f872a103858ec58a19042123ceRoboErik    private static long removeAlldayActiveEvents(Event event, Iterator<Event> iter, long colMask) {
50068655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // Remove the inactive allday events. An event on the active list
50168655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // becomes inactive when the end day is less than the current event's
50268655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // start day.
50368655b5af2b7e5f872a103858ec58a19042123ceRoboErik        while (iter.hasNext()) {
50468655b5af2b7e5f872a103858ec58a19042123ceRoboErik            final Event active = iter.next();
50568655b5af2b7e5f872a103858ec58a19042123ceRoboErik            if (active.endDay < event.startDay) {
50668655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask &= ~(1L << active.getColumn());
50768655b5af2b7e5f872a103858ec58a19042123ceRoboErik                iter.remove();
50868655b5af2b7e5f872a103858ec58a19042123ceRoboErik            }
50968655b5af2b7e5f872a103858ec58a19042123ceRoboErik        }
51068655b5af2b7e5f872a103858ec58a19042123ceRoboErik        return colMask;
51168655b5af2b7e5f872a103858ec58a19042123ceRoboErik    }
51268655b5af2b7e5f872a103858ec58a19042123ceRoboErik
51368655b5af2b7e5f872a103858ec58a19042123ceRoboErik    private static long removeNonAlldayActiveEvents(
51468655b5af2b7e5f872a103858ec58a19042123ceRoboErik            Event event, Iterator<Event> iter, long minDurationMillis, long colMask) {
51568655b5af2b7e5f872a103858ec58a19042123ceRoboErik        long start = event.getStartMillis();
51668655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // Remove the inactive events. An event on the active list
51768655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // becomes inactive when its end time is less than or equal to
51868655b5af2b7e5f872a103858ec58a19042123ceRoboErik        // the current event's start time.
51968655b5af2b7e5f872a103858ec58a19042123ceRoboErik        while (iter.hasNext()) {
52068655b5af2b7e5f872a103858ec58a19042123ceRoboErik            final Event active = iter.next();
52168655b5af2b7e5f872a103858ec58a19042123ceRoboErik
52268655b5af2b7e5f872a103858ec58a19042123ceRoboErik            final long duration = Math.max(
52368655b5af2b7e5f872a103858ec58a19042123ceRoboErik                    active.getEndMillis() - active.getStartMillis(), minDurationMillis);
52468655b5af2b7e5f872a103858ec58a19042123ceRoboErik            if ((active.getStartMillis() + duration) <= start) {
52568655b5af2b7e5f872a103858ec58a19042123ceRoboErik                colMask &= ~(1L << active.getColumn());
52668655b5af2b7e5f872a103858ec58a19042123ceRoboErik                iter.remove();
52768655b5af2b7e5f872a103858ec58a19042123ceRoboErik            }
52868655b5af2b7e5f872a103858ec58a19042123ceRoboErik        }
52968655b5af2b7e5f872a103858ec58a19042123ceRoboErik        return colMask;
53068655b5af2b7e5f872a103858ec58a19042123ceRoboErik    }
53168655b5af2b7e5f872a103858ec58a19042123ceRoboErik
532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static int findFirstZeroBit(long val) {
533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int ii = 0; ii < 64; ++ii) {
534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if ((val & (1L << ii)) == 0)
535146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return ii;
536146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
537146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return 64;
538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
540146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public final void dump() {
541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+-----------------------------------------+");
542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+        id = " + id);
543146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+     color = " + color);
544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+     title = " + title);
545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+  location = " + location);
546146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+    allDay = " + allDay);
547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+  startDay = " + startDay);
548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+    endDay = " + endDay);
549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+ startTime = " + startTime);
550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Log.e("Cal", "+   endTime = " + endTime);
5516d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        Log.e("Cal", "+ organizer = " + organizer);
5526d34cec523930368976bc8d358d0a6de1da3462cMichael Chan        Log.e("Cal", "+  guestwrt = " + guestsCanModify);
553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public final boolean intersects(int julianDay, int startMinute,
556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int endMinute) {
557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (endDay < julianDay) {
558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return false;
559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (startDay > julianDay) {
562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return false;
563146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
564146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
565146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (endDay == julianDay) {
566146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endTime < startMinute) {
567146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return false;
568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // An event that ends at the start minute should not be considered
570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // as intersecting the given time span, but don't exclude
571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // zero-length (or very short) events.
572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endTime == startMinute
573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    && (startTime != endTime || startDay != endDay)) {
574146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return false;
575146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
576146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
577146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
578146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (startDay == julianDay && startTime > endMinute) {
579146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return false;
580146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
581146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
582146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return true;
583146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
584146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Returns the event title and location separated by a comma.  If the
587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * location is already part of the title (at the end of the title), then
588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * just the title is returned.
589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the event title and location as a String
591146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public String getTitleAndLocation() {
593146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        String text = title.toString();
594146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
595146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // Append the location to the title, unless the title ends with the
596146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // location (for example, "meeting in building 42" ends with the
597146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // location).
598146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (location != null) {
599146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            String locationString = location.toString();
600146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (!text.endsWith(locationString)) {
601146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                text += ", " + locationString;
602146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
603146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
604146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return text;
605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setColumn(int column) {
608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mColumn = column;
609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getColumn() {
612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mColumn;
613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setMaxColumns(int maxColumns) {
616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mMaxColumns = maxColumns;
617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getMaxColumns() {
620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mMaxColumns;
621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setStartMillis(long startMillis) {
624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        this.startMillis = startMillis;
625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getStartMillis() {
628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return startMillis;
629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
631146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void setEndMillis(long endMillis) {
632146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        this.endMillis = endMillis;
633146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
634146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
635146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getEndMillis() {
636146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return endMillis;
637146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
638d031419da7900dab91ac9f512374d7e59bb74dceErik
63968655b5af2b7e5f872a103858ec58a19042123ceRoboErik    public boolean drawAsAllday() {
6401d92cbdf5b754f9da92303eaf554d8db7d7b0849RoboErik        // Use >= so we'll pick up Exchange allday events
6411d92cbdf5b754f9da92303eaf554d8db7d7b0849RoboErik        return allDay || endMillis - startMillis >= DateUtils.DAY_IN_MILLIS;
642d031419da7900dab91ac9f512374d7e59bb74dceErik    }
643146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
644