1 /* 2 * Copyright (C) 2007 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 17 package com.android.calendar; 18 19 import android.app.ExpandableListActivity; 20 import android.content.ContentResolver; 21 import android.content.Context; 22 import android.database.Cursor; 23 import android.database.ContentObserver; 24 import android.database.MatrixCursor; 25 import android.os.Bundle; 26 import android.os.Handler; 27 import android.provider.Calendar.Calendars; 28 import android.provider.Calendar; 29 import android.util.Log; 30 import android.view.View; 31 import android.view.Window; 32 import android.widget.AdapterView; 33 import android.widget.ExpandableListView; 34 35 36 public class SelectCalendarsActivity extends ExpandableListActivity 37 implements AdapterView.OnItemClickListener, View.OnClickListener { 38 39 private static final String TAG = "Calendar"; 40 private static final String EXPANDED_KEY = "is_expanded"; 41 private View mView = null; 42 private Cursor mCursor = null; 43 private ExpandableListView mList; 44 private SelectCalendarsAdapter mAdapter; 45 private static final String[] PROJECTION = new String[] { 46 Calendars._ID, 47 Calendars._SYNC_ACCOUNT_TYPE, 48 Calendars._SYNC_ACCOUNT 49 }; 50 51 @Override 52 protected void onCreate(Bundle icicle) { 53 super.onCreate(icicle); 54 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 55 setContentView(R.layout.calendars_activity); 56 getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, 57 Window.PROGRESS_INDETERMINATE_ON); 58 mList = getExpandableListView(); 59 mView = findViewById(R.id.calendars); 60 Context context = mView.getContext(); 61 //TODO Move managedQuery into a background thread. 62 //TODO change to something that supports group by queries. 63 mCursor = managedQuery(Calendars.CONTENT_URI, PROJECTION, 64 "1) GROUP BY (_sync_account", //Cheap hack to make WHERE a GROUP BY query 65 null /* selectionArgs */, 66 Calendars._SYNC_ACCOUNT /*sort order*/); 67 MatrixCursor accountsCursor = Utils.matrixCursorFromCursor(mCursor); 68 startManagingCursor(accountsCursor); 69 mAdapter = new SelectCalendarsAdapter(context, accountsCursor, this); 70 mList.setAdapter(mAdapter); 71 72 mList.setOnChildClickListener(this); 73 74 findViewById(R.id.btn_done).setOnClickListener(this); 75 findViewById(R.id.btn_discard).setOnClickListener(this); 76 77 // Start a background sync to get the list of calendars from the server. 78 startCalendarMetafeedSync(); 79 int count = mList.getCount(); 80 for(int i = 0; i < count; i++) { 81 mList.expandGroup(i); 82 } 83 } 84 85 @Override 86 protected void onResume() { 87 super.onResume(); 88 mAdapter.startRefreshStopDelay(); 89 } 90 91 @Override 92 protected void onPause() { 93 super.onPause(); 94 mAdapter.cancelRefreshStopDelay(); 95 } 96 97 @Override 98 protected void onSaveInstanceState(Bundle outState) { 99 super.onSaveInstanceState(outState); 100 boolean[] isExpanded; 101 mList = getExpandableListView(); 102 if(mList != null) { 103 int count = mList.getCount(); 104 isExpanded = new boolean[count]; 105 for(int i = 0; i < count; i++) { 106 isExpanded[i] = mList.isGroupExpanded(i); 107 } 108 } else { 109 isExpanded = null; 110 } 111 outState.putBooleanArray(EXPANDED_KEY, isExpanded); 112 //TODO Store this to preferences instead so it remains on restart 113 } 114 115 @Override 116 protected void onRestoreInstanceState(Bundle state) { 117 super.onRestoreInstanceState(state); 118 mList = getExpandableListView(); 119 boolean[] isExpanded = state.getBooleanArray(EXPANDED_KEY); 120 if(mList != null && isExpanded != null && mList.getCount() >= isExpanded.length) { 121 for(int i = 0; i < isExpanded.length; i++) { 122 if(isExpanded[i] && !mList.isGroupExpanded(i)) { 123 mList.expandGroup(i); 124 } else if(!isExpanded[i] && mList.isGroupExpanded(i)){ 125 mList.collapseGroup(i); 126 } 127 } 128 } 129 } 130 131 @Override 132 public boolean onChildClick(ExpandableListView parent, View view, int groupPosition, 133 int childPosition, long id) { 134 MultiStateButton button = (MultiStateButton) view.findViewById(R.id.multiStateButton); 135 return button.performClick(); 136 } 137 138 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 139 MultiStateButton button = (MultiStateButton) view.findViewById(R.id.multiStateButton); 140 button.performClick(); 141 } 142 143 /** {@inheritDoc} */ 144 public void onClick(View view) { 145 switch (view.getId()) { 146 case R.id.btn_done: { 147 doSaveAction(); 148 break; 149 } 150 case R.id.btn_discard: { 151 finish(); 152 break; 153 } 154 } 155 } 156 157 /*TODO*/ 158 private void doSaveAction() { 159 mAdapter.doSaveAction(); 160 finish(); 161 } 162 163 // startCalendarMetafeedSync() checks the server for an updated list of 164 // Calendars (in the background). 165 // 166 // If a Calendar is added on the web (and it is selected and not 167 // hidden) then it will be added to the list of calendars on the phone 168 // (when this finishes). When a new calendar from the 169 // web is added to the phone, then the events for that calendar are also 170 // downloaded from the web. 171 // 172 // This sync is done automatically in the background when the 173 // SelectCalendars activity is started. 174 private void startCalendarMetafeedSync() { 175 Bundle extras = new Bundle(); 176 extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); 177 extras.putBoolean("metafeedonly", true); 178 ContentResolver.requestSync(null /* all accounts */, 179 Calendars.CONTENT_URI.getAuthority(), extras); 180 } 181 } 182