diff options
Diffstat (limited to 'src/com/android/calendar/SelectCalendarsActivity.java')
-rw-r--r-- | src/com/android/calendar/SelectCalendarsActivity.java | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/src/com/android/calendar/SelectCalendarsActivity.java b/src/com/android/calendar/SelectCalendarsActivity.java new file mode 100644 index 00000000..25751e12 --- /dev/null +++ b/src/com/android/calendar/SelectCalendarsActivity.java @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.calendar; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.AsyncQueryHandler; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.provider.Calendar.Calendars; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.view.MenuItem.OnMenuItemClickListener; +import android.widget.AdapterView; +import android.widget.CheckBox; +import android.widget.ListView; + + +public class SelectCalendarsActivity extends Activity implements ListView.OnItemClickListener { + + private static final String TAG = "Calendar"; + private View mView = null; + private Cursor mCursor = null; + private QueryHandler mQueryHandler; + private SelectCalendarsAdapter mAdapter; + private static final String[] PROJECTION = new String[] { + Calendars._ID, + Calendars.DISPLAY_NAME, + Calendars.COLOR, + Calendars.SELECTED, + Calendars.SYNC_EVENTS + }; + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); + setContentView(R.layout.calendars_activity); + getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, + Window.PROGRESS_INDETERMINATE_ON); + mQueryHandler = new QueryHandler(getContentResolver()); + mView = findViewById(R.id.calendars); + ListView items = (ListView) mView.findViewById(R.id.items); + Context context = mView.getContext(); + mCursor = managedQuery(Calendars.CONTENT_URI, PROJECTION, + Calendars.SYNC_EVENTS + "=1", + null /* selectionArgs */, + Calendars.DEFAULT_SORT_ORDER); + + mAdapter = new SelectCalendarsAdapter(context, mCursor); + items.setAdapter(mAdapter); + items.setOnItemClickListener(this); + + // Start a background sync to get the list of calendars from the server. + startCalendarSync(); + } + + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + CheckBox box = (CheckBox) view.findViewById(R.id.checkbox); + box.toggle(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuItem item; + item = menu.add(0, 0, 0, R.string.add_calendars) + .setOnMenuItemClickListener(new ChangeCalendarAction(false /* not remove */)); + item.setIcon(android.R.drawable.ic_menu_add); + + item = menu.add(0, 0, 0, R.string.remove_calendars) + .setOnMenuItemClickListener(new ChangeCalendarAction(true /* remove */)); + item.setIcon(android.R.drawable.ic_menu_delete); + return true; + } + + /** + * ChangeCalendarAction is used both for adding and removing calendars. + * The constructor takes a boolean argument that is false if adding + * calendars and true if removing calendars. The user selects calendars + * to be added or removed from a pop-up list. + */ + public class ChangeCalendarAction implements OnMenuItemClickListener, + DialogInterface.OnClickListener, DialogInterface.OnMultiChoiceClickListener { + + int mNumItems; + long[] mCalendarIds; + boolean[] mIsChecked; + ContentResolver mContentResolver; + boolean mRemove; + + public ChangeCalendarAction(boolean remove) { + mContentResolver = SelectCalendarsActivity.this.getContentResolver(); + mRemove = remove; + } + + /* + * This is called when the user selects a calendar from either the + * "Add calendars" or "Remove calendars" popup dialog. + */ + public void onClick(DialogInterface dialog, int position, boolean isChecked) { + mIsChecked[position] = isChecked; + } + + /* + * This is called when the user presses the OK or Cancel button on the + * "Add calendars" or "Remove calendars" popup dialog. + */ + public void onClick(DialogInterface dialog, int which) { + // If the user cancelled the dialog, then do nothing. + if (which == DialogInterface.BUTTON2) { + return; + } + + boolean changesFound = false; + for (int position = 0; position < mNumItems; position++) { + // If this calendar wasn't selected, then skip it. + if (!mIsChecked[position]) { + continue; + } + changesFound = true; + + long id = mCalendarIds[position]; + Uri uri = ContentUris.withAppendedId(Calendars.CONTENT_URI, id); + ContentValues values = new ContentValues(); + int selected = 1; + if (mRemove) { + selected = 0; + } + values.put(Calendars.SELECTED, selected); + values.put(Calendars.SYNC_EVENTS, selected); + mContentResolver.update(uri, values, null, null); + } + + // If there were any changes, then update the list of calendars + // that are synced. + if (changesFound) { + mCursor.requery(); + } + } + + public boolean onMenuItemClick(MenuItem item) { + AlertDialog.Builder builder = new AlertDialog.Builder(SelectCalendarsActivity.this); + String selection; + if (mRemove) { + builder.setTitle(R.string.remove_calendars) + .setIcon(android.R.drawable.ic_dialog_alert); + selection = Calendars.SYNC_EVENTS + "=1"; + } else { + builder.setTitle(R.string.add_calendars); + selection = Calendars.SYNC_EVENTS + "=0"; + } + ContentResolver cr = getContentResolver(); + Cursor cursor = cr.query(Calendars.CONTENT_URI, PROJECTION, + selection, null /* selectionArgs */, + Calendars.DEFAULT_SORT_ORDER); + if (cursor == null) { + Log.w(TAG, "Cannot get cursor for calendars"); + return true; + } + + int count = cursor.getCount(); + mNumItems = count; + CharSequence[] calendarNames = new CharSequence[count]; + mCalendarIds = new long[count]; + mIsChecked = new boolean[count]; + try { + int pos = 0; + while (cursor.moveToNext()) { + mCalendarIds[pos] = cursor.getLong(0); + calendarNames[pos] = cursor.getString(1); + pos += 1; + } + } finally { + cursor.close(); + } + + builder.setMultiChoiceItems(calendarNames, null, this) + .setPositiveButton(R.string.ok_label, this) + .setNegativeButton(R.string.cancel_label, this) + .show(); + return true; + } + } + + private class QueryHandler extends AsyncQueryHandler { + public QueryHandler(ContentResolver cr) { + super(cr); + } + + @Override + protected void onQueryComplete(int token, Object cookie, Cursor cursor) { + getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, + Window.PROGRESS_VISIBILITY_OFF); + + // If the Activity is finishing, then close the cursor. + // Otherwise, use the new cursor in the adapter. + if (isFinishing()) { + stopManagingCursor(cursor); + cursor.close(); + } else { + if (cursor.getCount() == 0) { + // There are no calendars. This might happen if we lost + // the wireless connection (in airplane mode, for example). + // Leave the current list of calendars alone and pop up + // a dialog explaining that the connection is down. + // But allow the user to add and remove calendars. + return; + } + if (mCursor != null) { + stopManagingCursor(mCursor); + } + mCursor = cursor; + startManagingCursor(cursor); + mAdapter.changeCursor(cursor); + } + } + } + + // This class implements the menu option "Refresh list from server". + // (No longer used.) + public class RefreshAction implements Runnable { + public void run() { + startCalendarSync(); + } + } + + // startCalendarSync() checks the server for an updated list of Calendars + // (in the background) using an AsyncQueryHandler. + // + // Calendars are never removed from the phone due to a server sync. + // But if a Calendar is added on the web (and it is selected and not + // hidden) then it will be added to the list of calendars on the phone + // (when this asynchronous query finishes). When a new calendar from the + // web is added to the phone, then the events for that calendar are also + // downloaded from the web. + // + // This sync is done automatically in the background when the + // SelectCalendars activity is started. + private void startCalendarSync() { + getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, + Window.PROGRESS_VISIBILITY_ON); + + // TODO: make sure the user has login info. + + Uri uri = Calendars.LIVE_CONTENT_URI; + mQueryHandler.startQuery(0, null, uri, PROJECTION, + Calendars.SYNC_EVENTS + "=1", + null, Calendars.DEFAULT_SORT_ORDER); + } +} |