Calendar color picker Exchange account fix
Bug: 9196777
Change-Id: I21c97bf06ab51254d816f7c5cc2817f85e91d2eb
diff --git a/src/com/android/calendar/selectcalendars/CalendarColorCache.java b/src/com/android/calendar/selectcalendars/CalendarColorCache.java
new file mode 100644
index 0000000..0f9d14e
--- /dev/null
+++ b/src/com/android/calendar/selectcalendars/CalendarColorCache.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2013 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.selectcalendars;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.provider.CalendarContract.Colors;
+
+import com.android.calendar.AsyncQueryService;
+
+import java.util.HashSet;
+
+/**
+ * CalendarColorCache queries the provider and stores the account identifiers (name and type)
+ * of the accounts which contain optional calendar colors, and thus should allow for the
+ * user to choose calendar colors.
+ */
+public class CalendarColorCache {
+
+ private HashSet<String> mCache = new HashSet<String>();
+
+ private static final String SEPARATOR = "::";
+
+ private AsyncQueryService mService;
+ private OnCalendarColorsLoadedListener mListener;
+
+ private StringBuffer mStringBuffer = new StringBuffer();
+
+ private static String[] PROJECTION = new String[] {Colors.ACCOUNT_NAME, Colors.ACCOUNT_TYPE };
+
+ /**
+ * Interface which provides callback after provider query of calendar colors.
+ */
+ public interface OnCalendarColorsLoadedListener {
+
+ /**
+ * Callback after the set of accounts with additional calendar colors are loaded.
+ */
+ void onCalendarColorsLoaded();
+ }
+
+ public CalendarColorCache(Context context, OnCalendarColorsLoadedListener listener) {
+ mListener = listener;
+ mService = new AsyncQueryService(context) {
+
+ @Override
+ public void onQueryComplete(int token, Object cookie, Cursor c) {
+ if (c == null) {
+ return;
+ }
+ if (c.moveToFirst()) {
+ clear();
+ do {
+ insert(c.getString(0), c.getString(1));
+ } while (c.moveToNext());
+ mListener.onCalendarColorsLoaded();
+ }
+ if (c != null) {
+ c.close();
+ }
+ }
+ };
+ mService.startQuery(0, null, Colors.CONTENT_URI, PROJECTION,
+ Colors.COLOR_TYPE + "=" + Colors.TYPE_CALENDAR, null, null);
+ }
+
+ /**
+ * Inserts a specified account into the set.
+ */
+ private void insert(String accountName, String accountType) {
+ mCache.add(generateKey(accountName, accountType));
+ }
+
+ /**
+ * Does a set lookup to determine if a specified account has more optional calendar colors.
+ */
+ public boolean hasColors(String accountName, String accountType) {
+ return mCache.contains(generateKey(accountName, accountType));
+ }
+
+ /**
+ * Clears the cached set.
+ */
+ private void clear() {
+ mCache.clear();
+ }
+
+ /**
+ * Generates a single key based on account name and account type for map lookup/insertion.
+ */
+ private String generateKey(String accountName, String accountType) {
+ mStringBuffer.setLength(0);
+ return mStringBuffer.append(accountName).append(SEPARATOR).append(accountType).toString();
+ }
+}
diff --git a/src/com/android/calendar/selectcalendars/SelectCalendarsSimpleAdapter.java b/src/com/android/calendar/selectcalendars/SelectCalendarsSimpleAdapter.java
index 07bafae..6a75d2b 100644
--- a/src/com/android/calendar/selectcalendars/SelectCalendarsSimpleAdapter.java
+++ b/src/com/android/calendar/selectcalendars/SelectCalendarsSimpleAdapter.java
@@ -39,8 +39,10 @@
import com.android.calendar.CalendarColorPickerDialog;
import com.android.calendar.R;
import com.android.calendar.Utils;
+import com.android.calendar.selectcalendars.CalendarColorCache.OnCalendarColorsLoadedListener;
-public class SelectCalendarsSimpleAdapter extends BaseAdapter implements ListAdapter {
+public class SelectCalendarsSimpleAdapter extends BaseAdapter implements ListAdapter,
+ OnCalendarColorsLoadedListener {
private static final String TAG = "SelectCalendarsAdapter";
private static final String COLOR_PICKER_DIALOG_TAG = "ColorPickerDialog";
@@ -71,16 +73,22 @@
private int mColorColumn;
private int mVisibleColumn;
private int mOwnerAccountColumn;
+ private int mAccountNameColumn;
+ private int mAccountTypeColumn;
private static float mScale = 0;
private int mColorCalendarVisible;
private int mColorCalendarHidden;
private int mColorCalendarSecondaryVisible;
private int mColorCalendarSecondaryHidden;
+ private CalendarColorCache mCache;
+
private class CalendarRow {
long id;
String displayName;
String ownerAccount;
+ String accountName;
+ String accountType;
int color;
boolean selected;
}
@@ -103,6 +111,8 @@
NORMAL_ITEM_HEIGHT *= mScale;
}
+ mCache = new CalendarColorCache(context, this);
+
mFragmentManager = fm;
mColorPickerDialog = (CalendarColorPickerDialog)
fm.findFragmentByTag(COLOR_PICKER_DIALOG_TAG);
@@ -178,6 +188,8 @@
mColorColumn = c.getColumnIndexOrThrow(Calendars.CALENDAR_COLOR);
mVisibleColumn = c.getColumnIndexOrThrow(Calendars.VISIBLE);
mOwnerAccountColumn = c.getColumnIndexOrThrow(Calendars.OWNER_ACCOUNT);
+ mAccountNameColumn = c.getColumnIndexOrThrow(Calendars.ACCOUNT_NAME);
+ mAccountTypeColumn = c.getColumnIndexOrThrow(Calendars.ACCOUNT_TYPE);
mRowCount = c.getCount();
mData = new CalendarRow[(c.getCount())];
@@ -190,6 +202,8 @@
mData[p].color = c.getInt(mColorColumn);
mData[p].selected = c.getInt(mVisibleColumn) != 0;
mData[p].ownerAccount = c.getString(mOwnerAccountColumn);
+ mData[p].accountName = c.getString(mAccountNameColumn);
+ mData[p].accountType = c.getString(mAccountTypeColumn);
p++;
}
}
@@ -238,6 +252,11 @@
colorView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
+ // Purely for sanity check--view should be disabled if account has no more colors
+ if (!hasMoreColors(position)) {
+ return;
+ }
+
if (mColorPickerDialog == null) {
mColorPickerDialog = CalendarColorPickerDialog.newInstance(mData[position].id,
mIsTablet);
@@ -261,9 +280,11 @@
CheckBox syncCheckBox = (CheckBox) view.findViewById(R.id.sync);
if (syncCheckBox != null) {
+
// Full screen layout
syncCheckBox.setChecked(selected);
+ colorView.setEnabled(hasMoreColors(position));
LayoutParams layoutParam = calendarName.getLayoutParams();
TextView secondaryText = (TextView) view.findViewById(R.id.status);
if (!TextUtils.isEmpty(mData[position].ownerAccount)
@@ -288,7 +309,7 @@
} else {
// Tablet layout
- view.findViewById(R.id.color).setEnabled(selected);
+ view.findViewById(R.id.color).setEnabled(selected && hasMoreColors(position));
view.setBackgroundDrawable(getBackground(position, selected));
ViewGroup.LayoutParams newParams = view.getLayoutParams();
if (position == mData.length - 1) {
@@ -306,6 +327,10 @@
return view;
}
+ private boolean hasMoreColors(int position) {
+ return mCache.hasColors(mData[position].accountName, mData[position].accountType);
+ }
+
/**
* @param position position of the calendar item
* @param selected whether it is selected or not
@@ -355,4 +380,9 @@
public boolean hasStableIds() {
return true;
}
+
+ @Override
+ public void onCalendarColorsLoaded() {
+ notifyDataSetChanged();
+ }
}
diff --git a/src/com/android/calendar/selectcalendars/SelectCalendarsSyncAdapter.java b/src/com/android/calendar/selectcalendars/SelectCalendarsSyncAdapter.java
index 606c996..6e740bb 100644
--- a/src/com/android/calendar/selectcalendars/SelectCalendarsSyncAdapter.java
+++ b/src/com/android/calendar/selectcalendars/SelectCalendarsSyncAdapter.java
@@ -38,11 +38,12 @@
import com.android.calendar.CalendarColorPickerDialog;
import com.android.calendar.R;
import com.android.calendar.Utils;
+import com.android.calendar.selectcalendars.CalendarColorCache.OnCalendarColorsLoadedListener;
import java.util.HashMap;
public class SelectCalendarsSyncAdapter extends BaseAdapter
- implements ListAdapter, AdapterView.OnItemClickListener {
+ implements ListAdapter, AdapterView.OnItemClickListener, OnCalendarColorsLoadedListener {
private static final String TAG = "SelCalsAdapter";
private static final String COLOR_PICKER_DIALOG_TAG = "ColorPickerDialog";
@@ -50,6 +51,7 @@
private RectShape r = new RectShape();
private CalendarColorPickerDialog mColorPickerDialog;
+ private CalendarColorCache mCache;
private LayoutInflater mInflater;
private static final int LAYOUT = R.layout.calendar_sync_item;
@@ -61,6 +63,8 @@
private int mNameColumn;
private int mColorColumn;
private int mSyncedColumn;
+ private int mAccountNameColumn;
+ private int mAccountTypeColumn;
private boolean mIsTablet;
private FragmentManager mFragmentManager;
@@ -76,11 +80,14 @@
int color;
boolean synced;
boolean originalSynced;
+ String accountName;
+ String accountType;
}
public SelectCalendarsSyncAdapter(Context context, Cursor c, FragmentManager manager) {
super();
initData(c);
+ mCache = new CalendarColorCache(context, this);
mFragmentManager = manager;
mColorPickerDialog = (CalendarColorPickerDialog)
manager.findFragmentByTag(COLOR_PICKER_DIALOG_TAG);
@@ -106,6 +113,8 @@
mNameColumn = c.getColumnIndexOrThrow(Calendars.CALENDAR_DISPLAY_NAME);
mColorColumn = c.getColumnIndexOrThrow(Calendars.CALENDAR_COLOR);
mSyncedColumn = c.getColumnIndexOrThrow(Calendars.SYNC_EVENTS);
+ mAccountNameColumn = c.getColumnIndexOrThrow(Calendars.ACCOUNT_NAME);
+ mAccountTypeColumn = c.getColumnIndexOrThrow(Calendars.ACCOUNT_TYPE);
mRowCount = c.getCount();
mData = new CalendarRow[mRowCount];
@@ -118,6 +127,8 @@
mData[p].displayName = c.getString(mNameColumn);
mData[p].color = c.getInt(mColorColumn);
mData[p].originalSynced = c.getInt(mSyncedColumn) != 0;
+ mData[p].accountName = c.getString(mAccountNameColumn);
+ mData[p].accountType = c.getString(mAccountTypeColumn);
if (mChanges.containsKey(id)) {
mData[p].synced = mChanges.get(id).synced;
} else {
@@ -174,11 +185,17 @@
}
View colorView = view.findViewById(R.id.color);
+ colorView.setEnabled(hasMoreColors(position));
colorView.setBackgroundColor(color);
colorView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
+ // Purely for sanity check--view should be disabled if account has no more colors
+ if (!hasMoreColors(position)) {
+ return;
+ }
+
if (mColorPickerDialog == null) {
mColorPickerDialog = CalendarColorPickerDialog.newInstance(mData[position].id,
mIsTablet);
@@ -196,6 +213,10 @@
return view;
}
+ private boolean hasMoreColors(int position) {
+ return mCache.hasColors(mData[position].accountName, mData[position].accountType);
+ }
+
private static void setText(View view, int id, String text) {
if (TextUtils.isEmpty(text)) {
return;
@@ -259,4 +280,9 @@
public HashMap<Long, CalendarRow> getChanges() {
return mChanges;
}
+
+ @Override
+ public void onCalendarColorsLoaded() {
+ notifyDataSetChanged();
+ }
}
diff --git a/src/com/android/calendar/selectcalendars/SelectCalendarsSyncFragment.java b/src/com/android/calendar/selectcalendars/SelectCalendarsSyncFragment.java
index 4c148aa..abdd50d 100644
--- a/src/com/android/calendar/selectcalendars/SelectCalendarsSyncFragment.java
+++ b/src/com/android/calendar/selectcalendars/SelectCalendarsSyncFragment.java
@@ -36,14 +36,12 @@
import android.provider.CalendarContract.Calendars;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.TextView;
import com.android.calendar.AsyncQueryService;
-import com.android.calendar.CalendarColorPickerDialog;
import com.android.calendar.R;
import com.android.calendar.Utils;
import com.android.calendar.selectcalendars.SelectCalendarsSyncAdapter.CalendarRow;
@@ -68,6 +66,8 @@
Calendars.CALENDAR_DISPLAY_NAME,
Calendars.CALENDAR_COLOR,
Calendars.SYNC_EVENTS,
+ Calendars.ACCOUNT_NAME,
+ Calendars.ACCOUNT_TYPE,
"(" + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT + ") AS " + IS_PRIMARY, };
private TextView mSyncStatus;
diff --git a/src/com/android/calendar/selectcalendars/SelectSyncedCalendarsMultiAccountAdapter.java b/src/com/android/calendar/selectcalendars/SelectSyncedCalendarsMultiAccountAdapter.java
index 91610c6..58cdbdb 100644
--- a/src/com/android/calendar/selectcalendars/SelectSyncedCalendarsMultiAccountAdapter.java
+++ b/src/com/android/calendar/selectcalendars/SelectSyncedCalendarsMultiAccountAdapter.java
@@ -44,13 +44,14 @@
import com.android.calendar.CalendarColorPickerDialog;
import com.android.calendar.R;
import com.android.calendar.Utils;
+import com.android.calendar.selectcalendars.CalendarColorCache.OnCalendarColorsLoadedListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class SelectSyncedCalendarsMultiAccountAdapter extends CursorTreeAdapter implements
- View.OnClickListener {
+ View.OnClickListener, OnCalendarColorsLoadedListener {
private static final String TAG = "Calendar";
private static final String COLOR_PICKER_DIALOG_TAG = "ColorPickerDialog";
@@ -119,6 +120,7 @@
Calendars.VISIBLE,
Calendars.SYNC_EVENTS,
"(" + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT + ") AS " + IS_PRIMARY,
+ Calendars.ACCOUNT_TYPE
};
//Keep these in sync with the projection
private static final int ID_COLUMN = 0;
@@ -129,10 +131,13 @@
private static final int SELECTED_COLUMN = 5;
private static final int SYNCED_COLUMN = 6;
private static final int PRIMARY_COLUMN = 7;
+ private static final int ACCOUNT_TYPE_COLUMN = 8;
private static final int TAG_ID_CALENDAR_ID = R.id.calendar;
private static final int TAG_ID_SYNC_CHECKBOX = R.id.sync;
+ private CalendarColorCache mCache;
+
private class AsyncCalendarsUpdater extends AsyncQueryHandler {
public AsyncCalendarsUpdater(ContentResolver cr) {
@@ -216,6 +221,8 @@
mSyncedText = context.getString(R.string.synced);
mNotSyncedText = context.getString(R.string.not_synced);
+ mCache = new CalendarColorCache(context, this);
+
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mResolver = context.getContentResolver();
mActivity = act;
@@ -312,9 +319,12 @@
final long id = cursor.getLong(ID_COLUMN);
String name = cursor.getString(NAME_COLUMN);
String owner = cursor.getString(OWNER_COLUMN);
+ final String accountName = cursor.getString(ACCOUNT_COLUMN);
+ final String accountType = cursor.getString(ACCOUNT_TYPE_COLUMN);
int color = Utils.getDisplayColorFromColor(cursor.getInt(COLOR_COLUMN));
final View colorSquare = view.findViewById(R.id.color);
+ colorSquare.setEnabled(mCache.hasColors(accountName, accountType));
colorSquare.setBackgroundColor(color);
final View delegateParent = (View) colorSquare.getParent();
delegateParent.post(new Runnable() {
@@ -334,6 +344,9 @@
@Override
public void onClick(View v) {
+ if (!mCache.hasColors(accountName, accountType)) {
+ return;
+ }
if (mColorPickerDialog == null) {
mColorPickerDialog = CalendarColorPickerDialog.newInstance(id, mIsTablet);
} else {
@@ -449,4 +462,9 @@
CALENDARS_ORDERBY);
}
}
+
+ @Override
+ public void onCalendarColorsLoaded() {
+ notifyDataSetChanged();
+ }
}
diff --git a/src/com/android/calendar/selectcalendars/SelectVisibleCalendarsFragment.java b/src/com/android/calendar/selectcalendars/SelectVisibleCalendarsFragment.java
index d0bbdb6..5302896 100644
--- a/src/com/android/calendar/selectcalendars/SelectVisibleCalendarsFragment.java
+++ b/src/com/android/calendar/selectcalendars/SelectVisibleCalendarsFragment.java
@@ -16,13 +16,6 @@
package com.android.calendar.selectcalendars;
-import com.android.calendar.AsyncQueryService;
-import com.android.calendar.CalendarController.EventInfo;
-import com.android.calendar.CalendarController.EventType;
-import com.android.calendar.R;
-import com.android.calendar.CalendarController;
-import com.android.calendar.Utils;
-
import android.app.Activity;
import android.app.Fragment;
import android.content.ContentUris;
@@ -31,15 +24,23 @@
import android.net.Uri;
import android.os.Bundle;
import android.provider.CalendarContract.Calendars;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
+import com.android.calendar.AsyncQueryService;
+import com.android.calendar.CalendarController;
+import com.android.calendar.CalendarController.EventInfo;
+import com.android.calendar.CalendarController.EventType;
+import com.android.calendar.R;
+import com.android.calendar.Utils;
+import com.android.calendar.selectcalendars.CalendarColorCache.OnCalendarColorsLoadedListener;
+
public class SelectVisibleCalendarsFragment extends Fragment
- implements AdapterView.OnItemClickListener, CalendarController.EventHandler {
+ implements AdapterView.OnItemClickListener, CalendarController.EventHandler,
+ OnCalendarColorsLoadedListener {
private static final String TAG = "Calendar";
private static final String IS_PRIMARY = "\"primary\"";
@@ -49,6 +50,7 @@
private static final String[] PROJECTION = new String[] {
Calendars._ID,
Calendars.ACCOUNT_NAME,
+ Calendars.ACCOUNT_TYPE,
Calendars.OWNER_ACCOUNT,
Calendars.CALENDAR_DISPLAY_NAME,
Calendars.CALENDAR_COLOR,
@@ -183,4 +185,11 @@
public void handleEvent(EventInfo event) {
eventsChanged();
}
+
+ @Override
+ public void onCalendarColorsLoaded() {
+ if (mAdapter != null) {
+ mAdapter.notifyDataSetChanged();
+ }
+ }
}