CalendarController.java revision 9e89dca0902d13fe27fd2680cc15cbb470e40288
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.calendar;
18
19import static android.provider.Calendar.EVENT_BEGIN_TIME;
20import static android.provider.Calendar.EVENT_END_TIME;
21
22import android.app.ActionBar;
23import android.app.Activity;
24import android.content.ContentUris;
25import android.content.Intent;
26import android.net.Uri;
27import android.provider.Calendar.Events;
28import android.text.format.DateUtils;
29import android.text.format.Time;
30import android.util.Log;
31
32import java.util.ArrayList;
33import java.util.WeakHashMap;
34
35// Go to next/previous [agenda/day/week/month]
36// Go to range of days
37// Go to [agenda/day/week/month] view centering on time
38// Selected time and optionally event_id
39//
40// Setting
41// Select Calendars
42//
43// View [event id] at x,y
44// Edit [event id] at x,y
45// Delete [event id]
46// New event at [time]
47
48
49public class CalendarController {
50    private static final String TAG = "CalendarController";
51
52    private ArrayList<EventHandler> views = new ArrayList<EventHandler>(5);
53    private WeakHashMap<Object, Long> filters = new WeakHashMap<Object, Long>(1);
54
55    private Activity mActivity;
56
57    /**
58     * One of the event types that are sent to or from the controller
59     */
60    public interface EventType {
61        final long CREATE_EVENT = 1L;
62        final long VIEW_EVENT = 1L << 1;
63        final long EDIT_EVENT = 1L << 2;
64        final long DELETE_EVENT = 1L << 3;
65
66        final long SELECT = 1L << 4;
67        final long GO_TO = 1L << 5;
68
69        final long LAUNCH_MANAGE_CALENDARS = 1L << 6;
70        final long LAUNCH_SETTINGS = 1L << 7;
71    }
72
73    /**
74     * One of the Agenda/Day/Week/Month view types
75     */
76    public interface ViewType {
77        final long AGENDA = 1;
78        final long DAY = 2;
79        final long WEEK = 3;
80        final long MONTH = 4;
81    }
82
83    public static class EventInfo {
84        long eventType; // one of the EventType
85        long viewType; // one of the ViewType
86        long id; // event id
87        Time startTime; // start of a range of time.
88        Time endTime; // end of a range of time.
89        int x; // x coordinate in the activity space
90        int y; // y coordinate in the activity space
91    }
92
93    public interface EventHandler {
94        long getSupportedEventTypes();
95        void handleEvent(EventInfo event);
96
97        /**
98         * Returns the time in millis of the selected event in this view.
99         * @return the selected time in UTC milliseconds.
100         */
101        long getSelectedTime();
102
103        /**
104         * Changes the view to include the given time.
105         * @param time the desired time to view.
106         * @animate enable animation
107         */
108        void goTo(Time time, boolean animate);
109
110        /**
111         * Changes the view to include today's date.
112         */
113        void goToToday();
114
115        /**
116         * This is called when the user wants to create a new event and returns
117         * true if the new event should default to an all-day event.
118         * @return true if the new event should be an all-day event.
119         */
120        boolean getAllDay();
121
122        /**
123         * TODO comment
124         */
125        void eventsChanged();
126
127    }
128
129    public CalendarController(Activity activity) {
130        mActivity = activity;
131    }
132
133    /**
134     * Helper for sending New/View/Edit/Delete events
135     *
136     * @param sender object of the caller
137     * @param eventType one of {@link EventType}
138     * @param eventId event id
139     * @param start start time
140     * @param end end time
141     * @param x x coordinate in the activity space
142     * @param y y coordinate in the activity space
143     */
144    public void sendEventRelatedEvent(Object sender, long eventType, long eventId, long startMillis,
145            long endMillis, int x, int y) {
146        EventInfo info = new EventInfo();
147        info.eventType = eventType;
148        info.id = eventId;
149        info.startTime = new Time();
150        info.startTime.set(startMillis);
151        info.endTime = new Time();
152        info.endTime.set(endMillis);
153        info.x = x;
154        info.y = y;
155        this.sendEvent(sender, info);
156    }
157
158    /**
159     * Helper for sending non-calendar-event events
160     *
161     * @param sender object of the caller
162     * @param eventType one of {@link EventType}
163     * @param eventId event id
164     * @param start start time
165     * @param end end time
166     * @param viewType {@link ViewType}
167     */
168    public void sendEvent(Object sender, long eventType, Time start, Time end, long eventId,
169            long viewType) {
170        EventInfo info = new EventInfo();
171        info.eventType = eventType;
172        info.startTime = start;
173        info.endTime = end;
174        info.id = eventId;
175        info.viewType = viewType;
176        this.sendEvent(sender, info);
177    }
178
179    public void sendEvent(Object sender, final EventInfo event) {
180        // TODO Throw exception on invalid events
181
182        Log.d(TAG, eventInfoToString(event));
183
184        Long filteredTypes = filters.get(sender);
185        if (filteredTypes != null && (filteredTypes.longValue() & event.eventType) != 0) {
186            // Suppress event per filter
187            Log.d(TAG, "Event suppressed");
188            return;
189        }
190
191        // Create/View/Edit/Delete Event, Calendars, and Settings
192        long endTime = (event.endTime == null) ? -1 : event.endTime.toMillis(false);
193        if (event.eventType == EventType.CREATE_EVENT) {
194            launchCreateEvent(event.startTime.toMillis(false), endTime);
195            return;
196        } else if (event.eventType == EventType.VIEW_EVENT) {
197            launchViewEvent(event.id, event.startTime.toMillis(false), endTime);
198            return;
199        } else if (event.eventType == EventType.EDIT_EVENT) {
200            launchEditEvent(event.id, event.startTime.toMillis(false), endTime);
201            return;
202        } else if (event.eventType == EventType.DELETE_EVENT) {
203            launchDeleteEvent(event.id, event.startTime.toMillis(false), endTime);
204            return;
205        } else if (event.eventType == EventType.LAUNCH_MANAGE_CALENDARS) {
206            launchManageCalendars();
207            return;
208        } else if (event.eventType == EventType.LAUNCH_SETTINGS) {
209            launchSettings();
210            return;
211        }
212
213        // TODO Move to ActionBar?
214        setTitleInActionBar(event);
215
216        // Dispatch to view(s)
217        for (EventHandler view : views) {
218            if (view != null) {
219                boolean supportedEvent = (view.getSupportedEventTypes() & event.eventType) != 0;
220                if (supportedEvent) {
221                    view.handleEvent(event);
222                }
223            }
224        }
225    }
226
227    public void registerView(EventHandler view) {
228        views.add(view);
229    }
230
231    public void deregisterView(EventHandler view) {
232        views.remove(view);
233    }
234
235    public void filterBroadcasts(Object sender, long eventTypes) {
236        filters.put(sender, eventTypes);
237    }
238
239    private void setTitleInActionBar(EventInfo event) {
240        if (event.eventType != EventType.SELECT && event.eventType != EventType.GO_TO) {
241            return;
242        }
243
244        long start = event.startTime.toMillis(false /* use isDst */);
245        long end = start;
246
247        if (event.endTime != null && !event.startTime.equals(event.endTime)) {
248            end = event.endTime.toMillis(false /* use isDst */);
249        }
250        String msg = DateUtils.formatDateRange(mActivity, start, end, DateUtils.FORMAT_SHOW_DATE);
251
252        ActionBar ab = mActivity.getActionBar();
253        if (ab != null) {
254            ab.setTitle(msg);
255        }
256    }
257
258    private String eventInfoToString(EventInfo eventInfo) {
259        String tmp = "Unknown";
260
261        StringBuilder builder = new StringBuilder();
262        if ((eventInfo.eventType & EventType.SELECT) != 0) {
263            tmp = "Select time/event";
264        } else if ((eventInfo.eventType & EventType.GO_TO) != 0) {
265            tmp = "Go to time/event";
266        } else if ((eventInfo.eventType & EventType.CREATE_EVENT) != 0) {
267            tmp = "New event";
268        } else if ((eventInfo.eventType & EventType.VIEW_EVENT) != 0) {
269            tmp = "View event";
270        } else if ((eventInfo.eventType & EventType.EDIT_EVENT) != 0) {
271            tmp = "Edit event";
272        } else if ((eventInfo.eventType & EventType.DELETE_EVENT) != 0) {
273            tmp = "Delete event";
274        } else if ((eventInfo.eventType & EventType.LAUNCH_MANAGE_CALENDARS) != 0) {
275            tmp = "Launch select calendar";
276        } else if ((eventInfo.eventType & EventType.LAUNCH_SETTINGS) != 0) {
277            tmp = "Launch settings";
278        }
279        builder.append(tmp);
280        builder.append(": id=");
281        builder.append(eventInfo.id);
282        builder.append(", startTime=");
283        builder.append(eventInfo.startTime);
284        builder.append(", endTime=");
285        builder.append(eventInfo.endTime);
286        builder.append(", viewType=");
287        builder.append(eventInfo.viewType);
288        builder.append(", x=");
289        builder.append(eventInfo.x);
290        builder.append(", y=");
291        builder.append(eventInfo.y);
292        return builder.toString();
293    }
294
295    private void launchManageCalendars() {
296        Intent intent = new Intent(Intent.ACTION_VIEW);
297        intent.setClass(mActivity, SelectCalendarsActivity.class);
298        intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
299        mActivity.startActivity(intent);
300    }
301
302    private void launchSettings() {
303        Intent intent = new Intent(Intent.ACTION_VIEW);
304        intent.setClassName(mActivity, CalendarPreferenceActivity.class.getName());
305        intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
306        mActivity.startActivity(intent);
307    }
308
309    private void launchCreateEvent(long startMillis, long endMillis) {
310        Intent intent = new Intent(Intent.ACTION_VIEW);
311        intent.setClassName(mActivity, EditEventActivity.class.getName());
312        intent.putExtra(EVENT_BEGIN_TIME, startMillis);
313        intent.putExtra(EVENT_END_TIME, endMillis);
314        mActivity.startActivity(intent);
315    }
316
317    private void launchViewEvent(long eventId, long startMillis, long endMillis) {
318        Intent intent = new Intent(Intent.ACTION_VIEW);
319        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);
320        intent.setData(eventUri);
321        intent.setClassName(mActivity, EventInfoActivity.class.getName());
322        intent.putExtra(EVENT_BEGIN_TIME, startMillis);
323        intent.putExtra(EVENT_END_TIME, endMillis);
324        mActivity.startActivity(intent);
325    }
326
327    private void launchEditEvent(long eventId, long startMillis, long endMillis) {
328        Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);
329        Intent intent = new Intent(Intent.ACTION_EDIT, uri);
330        intent.putExtra(EVENT_BEGIN_TIME, startMillis);
331        intent.putExtra(EVENT_END_TIME, endMillis);
332        intent.setClass(mActivity, EditEventActivity.class);
333        mActivity.startActivity(intent);
334    }
335
336    private void launchDeleteEvent(long eventId, long startMillis, long endMillis) {
337        launchDeleteEventAndFinish(null, eventId, startMillis, endMillis, -1);
338    }
339
340    private void launchDeleteEventAndFinish(Activity parentActivity, long eventId, long startMillis,
341            long endMillis, int deleteWhich) {
342        DeleteEventHelper deleteEventHelper = new DeleteEventHelper(mActivity, parentActivity,
343                parentActivity != null /* exit when done */);
344        deleteEventHelper.delete(startMillis, endMillis, eventId, deleteWhich);
345    }
346}
347