diff --git a/res/layout/mailbox_list_item.xml b/res/layout/mailbox_list_item.xml index 2aa7aa8ec..3a45dea4e 100644 --- a/res/layout/mailbox_list_item.xml +++ b/res/layout/mailbox_list_item.xml @@ -54,4 +54,13 @@ android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="?android:attr/textColorPrimary" /> + + diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 4df819e99..c675b048e 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -177,4 +177,13 @@ @drawable/ic_list_spam + + + + @color/combined_view_account_color_1 + @color/combined_view_account_color_2 + @color/combined_view_account_color_3 + @color/combined_view_account_color_4 + @color/combined_view_account_color_5 + diff --git a/res/values/colors.xml b/res/values/colors.xml index c301a4b19..f82d7c0c3 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -29,4 +29,12 @@ #ff808080 + + + + #ff0080ff + #ff800040 + #ff009b8b + #fff4fd04 + #ffe65020 diff --git a/res/values/dimensions.xml b/res/values/dimensions.xml index c11967aac..cd1a120e4 100644 --- a/res/values/dimensions.xml +++ b/res/values/dimensions.xml @@ -4,9 +4,9 @@ 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. @@ -26,4 +26,8 @@ 64dip 72dip 720dip + 35dip + 8dip + 32dip + 65dip diff --git a/src/com/android/email/Email.java b/src/com/android/email/Email.java index 02b9b677e..3bc12ae46 100644 --- a/src/com/android/email/Email.java +++ b/src/com/android/email/Email.java @@ -162,49 +162,10 @@ public class Email extends Application { public static final String EXCHANGE_ACCOUNT_MANAGER_TYPE = "com.android.exchange"; public static final String POP_IMAP_ACCOUNT_MANAGER_TYPE = "com.android.email"; - // The color chip resources and the RGB color values in the array below must be kept in sync - private static final int[] ACCOUNT_COLOR_CHIP_RES_IDS = new int[] { - R.drawable.appointment_indicator_leftside_1, - R.drawable.appointment_indicator_leftside_2, - R.drawable.appointment_indicator_leftside_3, - R.drawable.appointment_indicator_leftside_4, - R.drawable.appointment_indicator_leftside_5, - R.drawable.appointment_indicator_leftside_6, - R.drawable.appointment_indicator_leftside_7, - R.drawable.appointment_indicator_leftside_8, - R.drawable.appointment_indicator_leftside_9, - }; - - private static final int[] ACCOUNT_COLOR_CHIP_RGBS = new int[] { - 0x71aea7, - 0x621919, - 0x18462f, - 0xbf8e52, - 0x001f79, - 0xa8afc2, - 0x6b64c4, - 0x738359, - 0x9d50a4, - }; - private static File sTempDirectory; private static Thread sUiThread; - /* package for testing */ static int getColorIndexFromAccountId(long accountId) { - // Account id is 1-based, so - 1. - // Use abs so that it won't possibly return negative. - return Math.abs((int) (accountId - 1) % ACCOUNT_COLOR_CHIP_RES_IDS.length); - } - - public static int getAccountColorResourceId(long accountId) { - return ACCOUNT_COLOR_CHIP_RES_IDS[getColorIndexFromAccountId(accountId)]; - } - - public static int getAccountColor(long accountId) { - return ACCOUNT_COLOR_CHIP_RGBS[getColorIndexFromAccountId(accountId)]; - } - public static void setTempDirectory(Context context) { sTempDirectory = context.getCacheDir(); } diff --git a/src/com/android/email/ResourceHelper.java b/src/com/android/email/ResourceHelper.java new file mode 100644 index 000000000..b286ba238 --- /dev/null +++ b/src/com/android/email/ResourceHelper.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010 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.email; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Paint; + +/** + * Helper class to load resources. + */ +public class ResourceHelper { + private static ResourceHelper sInstance; + private final Context mContext; + private final Resources mResources; + + private final int[] mAccountColors; + private final Paint[] mAccountColorPaints; + + private ResourceHelper(Context context) { + mContext = context; + mResources = mContext.getResources(); + + mAccountColors = mResources.getIntArray(R.array.combined_view_account_colors); + mAccountColorPaints = new Paint[mAccountColors.length]; + for (int i = 0; i < mAccountColors.length; i++) { + Paint p = new Paint(); + p.setColor(mAccountColors[i]); + mAccountColorPaints[i] = p; + } + } + + public static synchronized ResourceHelper getInstance(Context context) { + if (sInstance == null) { + sInstance = new ResourceHelper(context); + } + return sInstance; + } + + /* package */ int getAccountColorIndex(long accountId) { + // The account ID is 1-based, so -1. + // Use abs so that it'd work for -1 as well. + return Math.abs((int) ((accountId - 1) % mAccountColors.length)); + } + + /** + * @return color for an account. + */ + public int getAccountColor(long accountId) { + return mAccountColors[getAccountColorIndex(accountId)]; + } + + /** + * @return {@link Paint} equivalent to {@link #getAccountColor}. + */ + public Paint getAccountColorPaint(long accountId) { + return mAccountColorPaints[getAccountColorIndex(accountId)]; + } +} diff --git a/src/com/android/email/activity/AccountsAdapter.java b/src/com/android/email/activity/AccountsAdapter.java index 9692bd1c7..056bd984b 100644 --- a/src/com/android/email/activity/AccountsAdapter.java +++ b/src/com/android/email/activity/AccountsAdapter.java @@ -218,9 +218,9 @@ public class AccountsAdapter extends CursorAdapter { itemView.mAccountId = cursor.getLong(Account.CONTENT_ID_COLUMN); long accountId = cursor.getLong(Account.CONTENT_ID_COLUMN); - View chipView = view.findViewById(R.id.chip); - chipView.setBackgroundResource(Email.getAccountColorResourceId(accountId)); - chipView.setVisibility(View.VISIBLE); + + // No color chip for now. TODO Revisit for phone UI + view.findViewById(R.id.chip).setVisibility(View.GONE); String text = cursor.getString(Account.CONTENT_DISPLAY_NAME_COLUMN); if (text != null) { diff --git a/src/com/android/email/activity/MailboxesAdapter.java b/src/com/android/email/activity/MailboxesAdapter.java index 5109853e2..a022c6c8c 100644 --- a/src/com/android/email/activity/MailboxesAdapter.java +++ b/src/com/android/email/activity/MailboxesAdapter.java @@ -18,6 +18,7 @@ package com.android.email.activity; import com.android.email.Email; import com.android.email.R; +import com.android.email.ResourceHelper; import com.android.email.Utility; import com.android.email.data.ThrottlingCursorLoader; import com.android.email.provider.EmailContent; @@ -111,6 +112,7 @@ import android.widget.TextView; private final Context mContext; private final LayoutInflater mInflater; + private final ResourceHelper mResourceHelper; private final int mMode; private static boolean sEnableUpdate = true; @@ -122,6 +124,7 @@ import android.widget.TextView; mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mMode = mode; mCallback = callback; + mResourceHelper = ResourceHelper.getInstance(mContext); } /** @@ -260,12 +263,13 @@ import android.widget.TextView; } private void bindViewNormalMode(View view, Context context, Cursor cursor) { + final boolean isAccount = isAccountRow(cursor); final int type = cursor.getInt(COLUMN_TYPE); - final long mailboxId = cursor.getLong(COLUMN_ID); + final long id = cursor.getLong(COLUMN_ID); MailboxListItem listItem = (MailboxListItem)view; listItem.mMailboxType = type; - listItem.mMailboxId = mailboxId; + listItem.mMailboxId = id; listItem.mAdapter = this; // Set the background depending on whether we're in drag mode, the mailbox is a valid @@ -301,7 +305,15 @@ import android.widget.TextView; // Set folder icon ((ImageView) view.findViewById(R.id.folder_icon)).setImageDrawable( - Utility.FolderProperties.getInstance(context).getIcon(type, mailboxId)); + Utility.FolderProperties.getInstance(context).getIcon(type, id)); + + final View chipView = view.findViewById(R.id.color_chip); + if (isAccount) { + chipView.setVisibility(View.VISIBLE); + chipView.setBackgroundColor(mResourceHelper.getAccountColor(id)); + } else { + chipView.setVisibility(View.GONE); + } } private View newViewNormalMode(Context context, Cursor cursor, ViewGroup parent) { diff --git a/src/com/android/email/activity/MessageListFragment.java b/src/com/android/email/activity/MessageListFragment.java index 2c82f01b8..e02af7ec1 100644 --- a/src/com/android/email/activity/MessageListFragment.java +++ b/src/com/android/email/activity/MessageListFragment.java @@ -1089,6 +1089,7 @@ public class MessageListFragment extends ListFragment // Update the list mListAdapter.changeCursor(cursor); + mListAdapter.setShowColorChips(mMailboxId < 0); // Show chips if combined view setListAdapter(mListAdapter); setListShown(true); diff --git a/src/com/android/email/activity/MessageListItem.java b/src/com/android/email/activity/MessageListItem.java index 79e05f767..fc882b712 100644 --- a/src/com/android/email/activity/MessageListItem.java +++ b/src/com/android/email/activity/MessageListItem.java @@ -23,6 +23,7 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.FontMetricsInt; import android.graphics.Typeface; @@ -98,6 +99,8 @@ public class MessageListItem extends View { public boolean mHasAttachment = false; public boolean mHasInvite = true; public boolean mIsFavorite = false; + /** {@link Paint} for account color chips. null if no chips should be drawn. */ + public Paint mColorChipPaint; private int mMode = -1; @@ -117,6 +120,10 @@ public class MessageListItem extends View { private static int sItemHeightWide; private static int sItemHeightNarrow; private static int sMinimumWidthWideMode; + private static int sColorTipWidth; + private static int sColorTipHeight; + private static int sColorTipRightMarginOnNarrow; + private static int sColorTipRightMarginOnWide; public int mSnippetLineCount = NEEDS_LAYOUT; private final CharSequence[] mSnippetLines = new CharSequence[MAX_SUBJECT_SNIPPET_LINES]; @@ -147,6 +154,14 @@ public class MessageListItem extends View { r.getDimensionPixelSize(R.dimen.message_list_item_height_narrow); sMinimumWidthWideMode = r.getDimensionPixelSize(R.dimen.message_list_item_minimum_width_wide_mode); + sColorTipWidth = + r.getDimensionPixelSize(R.dimen.message_list_item_color_tip_width); + sColorTipHeight = + r.getDimensionPixelSize(R.dimen.message_list_item_color_tip_height); + sColorTipRightMarginOnNarrow = + r.getDimensionPixelSize(R.dimen.message_list_item_color_tip_right_margin_on_narrow); + sColorTipRightMarginOnWide = + r.getDimensionPixelSize(R.dimen.message_list_item_color_tip_right_margin_on_wide); sDefaultPaint.setTypeface(Typeface.DEFAULT); sDefaultPaint.setTextSize(sTextSize); @@ -312,6 +327,14 @@ public class MessageListItem extends View { snippetY = senderY + lineHeight + sPaddingVerySmall; } + // Draw the color chip + if (mColorChipPaint != null) { + final int rightMargin = (mMode == MODE_WIDE) + ? sColorTipRightMarginOnWide : sColorTipRightMarginOnNarrow; + final int x = mViewWidth - rightMargin - sColorTipWidth; + canvas.drawRect(x, 0, x + sColorTipWidth, sColorTipHeight, mColorChipPaint); + } + // Draw the checkbox int checkboxLeft = (sCheckboxHitWidth - sSelectedIconOff.getWidth()) / 2; int checkboxTop = (mViewHeight - sSelectedIconOff.getHeight()) / 2; diff --git a/src/com/android/email/activity/MessagesAdapter.java b/src/com/android/email/activity/MessagesAdapter.java index a2f39cf10..d97fad959 100644 --- a/src/com/android/email/activity/MessagesAdapter.java +++ b/src/com/android/email/activity/MessagesAdapter.java @@ -18,6 +18,7 @@ package com.android.email.activity; import com.android.email.Email; import com.android.email.R; +import com.android.email.ResourceHelper; import com.android.email.Utility; import com.android.email.data.ThrottlingCursorLoader; import com.android.email.provider.EmailContent; @@ -64,6 +65,11 @@ import java.util.Set; public static final int COLUMN_FLAGS = 9; public static final int COLUMN_SNIPPET = 10; + private final ResourceHelper mResourceHelper; + + /** If true, show color chips. */ + private boolean mShowColorChips; + /** * Set of seleced message IDs. */ @@ -84,6 +90,7 @@ import java.util.Set; public MessagesAdapter(Context context, Callback callback) { super(context.getApplicationContext(), null, 0 /* no auto requery */); + mResourceHelper = ResourceHelper.getInstance(context); mCallback = callback; } @@ -105,6 +112,13 @@ import java.util.Set; } } + /** + * Set true for combined mailboxes. + */ + public void setShowColorChips(boolean show) { + mShowColorChips = show; + } + public Set getSelectedSet() { return mSelectedSet; } @@ -122,7 +136,8 @@ import java.util.Set; // Load the public fields in the view (for later use) itemView.mMessageId = cursor.getLong(COLUMN_ID); itemView.mMailboxId = cursor.getLong(COLUMN_MAILBOX_KEY); - itemView.mAccountId = cursor.getLong(COLUMN_ACCOUNT_KEY); + final long accountId = cursor.getLong(COLUMN_ACCOUNT_KEY); + itemView.mAccountId = accountId; itemView.mRead = cursor.getInt(COLUMN_READ) != 0; itemView.mIsFavorite = cursor.getInt(COLUMN_FAVORITE) != 0; itemView.mHasInvite = @@ -132,6 +147,8 @@ import java.util.Set; itemView.mSender = cursor.getString(COLUMN_DISPLAY_NAME); itemView.mSnippet = cursor.getString(COLUMN_SNIPPET); itemView.mSnippetLineCount = MessageListItem.NEEDS_LAYOUT; + itemView.mColorChipPaint = + mShowColorChips ? mResourceHelper.getAccountColorPaint(accountId) : null; String text = cursor.getString(COLUMN_SUBJECT); String snippet = cursor.getString(COLUMN_SNIPPET); @@ -199,15 +216,15 @@ import java.util.Set; if (Email.DEBUG_LIFECYCLE && Email.DEBUG) { Log.d(Email.LOG_TAG, "MessagesAdapter createLoader mailboxId=" + mailboxId); } - return new MessagesCursor(context, mailboxId); + return new MessagesCursorLoader(context, mailboxId); } - private static class MessagesCursor extends ThrottlingCursorLoader { + private static class MessagesCursorLoader extends ThrottlingCursorLoader { private final Context mContext; private final long mMailboxId; - public MessagesCursor(Context context, long mailboxId) { + public MessagesCursorLoader(Context context, long mailboxId) { // Initialize with no where clause. We'll set it later. super(context, EmailContent.Message.CONTENT_URI, MESSAGE_PROJECTION, null, null, diff --git a/src/com/android/exchange/utility/CalendarUtilities.java b/src/com/android/exchange/utility/CalendarUtilities.java index 03a0a6d99..e1879f653 100644 --- a/src/com/android/exchange/utility/CalendarUtilities.java +++ b/src/com/android/exchange/utility/CalendarUtilities.java @@ -18,6 +18,7 @@ package com.android.exchange.utility; import com.android.email.Email; import com.android.email.R; +import com.android.email.ResourceHelper; import com.android.email.Utility; import com.android.email.mail.Address; import com.android.email.provider.EmailContent; @@ -1215,7 +1216,8 @@ public class CalendarUtilities { // TODO Coordinate account colors w/ Calendar, if possible // Make Email account color opaque - cv.put(Calendars.COLOR, 0xFF000000 | Email.getAccountColor(account.mId)); + int color = ResourceHelper.getInstance(service.mContext).getAccountColor(account.mId); + cv.put(Calendars.COLOR, color); cv.put(Calendars.TIMEZONE, Time.getCurrentTimezone()); cv.put(Calendars.ACCESS_LEVEL, Calendars.OWNER_ACCESS); cv.put(Calendars.OWNER_ACCOUNT, account.mEmailAddress); diff --git a/tests/src/com/android/email/EmailTest.java b/tests/src/com/android/email/EmailTest.java deleted file mode 100644 index 69e4178e9..000000000 --- a/tests/src/com/android/email/EmailTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2010 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.email; - -import junit.framework.TestCase; - -public class EmailTest extends TestCase { - public void testGetColorIndexFromAccountId() { - // First account (id=1) gets index 0. - assertEquals(0, Email.getColorIndexFromAccountId(1)); - assertEquals(1, Email.getColorIndexFromAccountId(2)); - - // Never return negative. - assertTrue(Email.getColorIndexFromAccountId(-5) >= 0); - - // Shouldn't throw ArrayIndexOutOfRange or anything. - for (int i = -100; i < 100; i++) { - Email.getAccountColorResourceId(i); - Email.getAccountColor(i); - } - } -} diff --git a/tests/src/com/android/email/ResourceHelperTest.java b/tests/src/com/android/email/ResourceHelperTest.java new file mode 100644 index 000000000..2900dc537 --- /dev/null +++ b/tests/src/com/android/email/ResourceHelperTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 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.email; + +import android.graphics.Paint; +import android.test.AndroidTestCase; + +public class ResourceHelperTest extends AndroidTestCase { + private ResourceHelper mResourceHelper; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mResourceHelper = ResourceHelper.getInstance(getContext()); + } + + public void testGetAccountColor() { + Integer lastColor = null; + Paint lastPaint = null; + + for (long accountId = -1; accountId < 100; accountId++) { + // Shouldn't throw any exception (such as IndexOutOfRange) + Integer color = mResourceHelper.getAccountColor(accountId); + Paint paint = mResourceHelper.getAccountColorPaint(accountId); + + // Should be different from the previous one + assertNotNull(color); + assertNotNull(paint); + assertFalse(color.equals(lastColor)); + assertFalse(paint.equals(lastPaint)); + + lastColor = color; + lastPaint = paint; + } + } +}