1 /* 2 * Copyright (C) 2012 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.mail.widget; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.graphics.Bitmap; 22 import android.graphics.BitmapFactory; 23 import android.graphics.Typeface; 24 import android.text.Spannable; 25 import android.text.SpannableStringBuilder; 26 import android.text.style.AbsoluteSizeSpan; 27 import android.text.style.CharacterStyle; 28 import android.text.style.ForegroundColorSpan; 29 import android.text.style.StyleSpan; 30 import android.view.View; 31 import android.widget.RemoteViews; 32 33 import com.android.mail.R; 34 import com.android.mail.providers.Conversation; 35 import com.android.mail.providers.Folder; 36 import com.android.mail.ui.FolderDisplayer; 37 import com.android.mail.utils.FolderUri; 38 39 public class WidgetConversationListItemViewBuilder { 40 // Static colors 41 private static int SUBJECT_TEXT_COLOR_READ; 42 private static int SUBJECT_TEXT_COLOR_UNREAD; 43 private static int SNIPPET_TEXT_COLOR; 44 private static int DATE_TEXT_COLOR_READ; 45 private static int DATE_TEXT_COLOR_UNREAD; 46 47 // Static bitmap 48 private static Bitmap ATTACHMENT; 49 50 private WidgetFolderDisplayer mFolderDisplayer; 51 52 /** 53 * Label Displayer for Widget 54 */ 55 protected static class WidgetFolderDisplayer extends FolderDisplayer { 56 public WidgetFolderDisplayer(Context context) { 57 super(context); 58 } 59 60 // Maximum number of folders we want to display 61 private static final int MAX_DISPLAYED_FOLDERS_COUNT = 3; 62 63 /* 64 * Load Conversation Labels 65 */ 66 @Override 67 public void loadConversationFolders(Conversation conv, final FolderUri ignoreFolderUri, 68 final int ignoreFolderType) { 69 super.loadConversationFolders(conv, ignoreFolderUri, ignoreFolderType); 70 } 71 72 private static int getFolderViewId(int position) { 73 switch (position) { 74 case 0: 75 return R.id.widget_folder_0; 76 case 1: 77 return R.id.widget_folder_1; 78 case 2: 79 return R.id.widget_folder_2; 80 } 81 return 0; 82 } 83 84 /** 85 * Display folders 86 */ 87 public void displayFolders(RemoteViews remoteViews) { 88 int displayedFolder = 0; 89 for (Folder folderValues : mFoldersSortedSet) { 90 int viewId = getFolderViewId(displayedFolder); 91 if (viewId == 0) { 92 continue; 93 } 94 remoteViews.setViewVisibility(viewId, View.VISIBLE); 95 int color[] = new int[] 96 {folderValues.getBackgroundColor(mFolderDrawableResources.defaultBgColor)}; 97 Bitmap bitmap = Bitmap.createBitmap(color, 1, 1, Bitmap.Config.RGB_565); 98 remoteViews.setImageViewBitmap(viewId, bitmap); 99 100 if (++displayedFolder == MAX_DISPLAYED_FOLDERS_COUNT) { 101 break; 102 } 103 } 104 105 for (int i = displayedFolder; i < MAX_DISPLAYED_FOLDERS_COUNT; i++) { 106 remoteViews.setViewVisibility(getFolderViewId(i), View.GONE); 107 } 108 } 109 } 110 111 /* 112 * Get font sizes and bitmaps from Resources 113 */ 114 public WidgetConversationListItemViewBuilder(Context context) { 115 final Resources res = context.getResources(); 116 117 // Initialize colors 118 SUBJECT_TEXT_COLOR_READ = res.getColor(R.color.subject_text_color_read); 119 SUBJECT_TEXT_COLOR_UNREAD = res.getColor(R.color.subject_text_color_unread); 120 SNIPPET_TEXT_COLOR = res.getColor(R.color.snippet_text_color); 121 DATE_TEXT_COLOR_READ = res.getColor(R.color.date_text_color_read); 122 DATE_TEXT_COLOR_UNREAD = res.getColor(R.color.date_text_color_unread); 123 124 // Initialize Bitmap 125 ATTACHMENT = BitmapFactory.decodeResource(res, R.drawable.ic_attach_file_18dp); 126 } 127 128 /* 129 * Add size, color and style to a given text 130 */ 131 private static SpannableStringBuilder addStyle(CharSequence text, int size, int color) { 132 final SpannableStringBuilder builder = new SpannableStringBuilder(text); 133 builder.setSpan( 134 new AbsoluteSizeSpan(size), 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 135 if (color != 0) { 136 builder.setSpan(new ForegroundColorSpan(color), 0, text.length(), 137 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 138 } 139 return builder; 140 } 141 142 /* 143 * Return the full View 144 */ 145 public RemoteViews getStyledView(final Context context, final CharSequence date, 146 final Conversation conversation, final FolderUri folderUri, final int ignoreFolderType, 147 final SpannableStringBuilder senders, String subject) { 148 149 final boolean isUnread = !conversation.read; 150 final String snippet = conversation.getSnippet(); 151 final boolean hasAttachments = conversation.hasAttachments; 152 final Resources res = context.getResources(); 153 final int dateFontSize = res.getDimensionPixelSize(R.dimen.widget_date_font_size); 154 final int subjectFontSize = res.getDimensionPixelSize(R.dimen.widget_subject_font_size); 155 156 // Add style to date 157 final int dateColor = isUnread ? DATE_TEXT_COLOR_UNREAD : DATE_TEXT_COLOR_READ; 158 final SpannableStringBuilder dateBuilder = addStyle(date, dateFontSize, dateColor); 159 if (isUnread) { 160 dateBuilder.setSpan(new StyleSpan(Typeface.BOLD), 0, date.length(), 161 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 162 } 163 164 subject = Conversation.getSubjectForDisplay(context, null /* badgeText */, subject); 165 final SpannableStringBuilder subjectBuilder = new SpannableStringBuilder(subject); 166 if (isUnread) { 167 subjectBuilder.setSpan(new StyleSpan(Typeface.BOLD), 0, subject.length(), 168 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 169 } 170 final int subjectColor = isUnread ? SUBJECT_TEXT_COLOR_UNREAD : SUBJECT_TEXT_COLOR_READ; 171 final CharacterStyle subjectStyle = new ForegroundColorSpan(subjectColor); 172 subjectBuilder.setSpan(subjectStyle, 0, subjectBuilder.length(), 173 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 174 final CharSequence styledSubject = addStyle(subjectBuilder, subjectFontSize, 0); 175 176 final SpannableStringBuilder snippetBuilder = new SpannableStringBuilder(snippet); 177 snippetBuilder.setSpan(new ForegroundColorSpan(SNIPPET_TEXT_COLOR), 0, 178 snippetBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 179 final CharSequence styledSnippet = addStyle(snippetBuilder, subjectFontSize, 0); 180 181 // Paper clip for attachment 182 Bitmap paperclipBitmap = null; 183 if (hasAttachments) { 184 paperclipBitmap = ATTACHMENT; 185 } 186 187 // Inflate and fill out the remote view 188 final RemoteViews remoteViews = new RemoteViews( 189 context.getPackageName(), R.layout.widget_conversation_list_item); 190 remoteViews.setTextViewText(R.id.widget_senders, senders); 191 remoteViews.setTextViewText(R.id.widget_date, dateBuilder); 192 remoteViews.setTextViewText(R.id.widget_subject, styledSubject); 193 remoteViews.setTextViewText(R.id.widget_snippet, styledSnippet); 194 if (paperclipBitmap != null) { 195 remoteViews.setViewVisibility(R.id.widget_attachment, View.VISIBLE); 196 remoteViews.setImageViewBitmap(R.id.widget_attachment, paperclipBitmap); 197 } else { 198 remoteViews.setViewVisibility(R.id.widget_attachment, View.GONE); 199 } 200 if (isUnread) { 201 remoteViews.setViewVisibility(R.id.widget_unread_background, View.VISIBLE); 202 remoteViews.setViewVisibility(R.id.widget_read_background, View.GONE); 203 } else { 204 remoteViews.setViewVisibility(R.id.widget_unread_background, View.GONE); 205 remoteViews.setViewVisibility(R.id.widget_read_background, View.VISIBLE); 206 } 207 if (context.getResources().getBoolean(R.bool.display_folder_colors_in_widget)) { 208 mFolderDisplayer = new WidgetFolderDisplayer(context); 209 mFolderDisplayer.loadConversationFolders(conversation, folderUri, ignoreFolderType); 210 mFolderDisplayer.displayFolders(remoteViews); 211 } 212 213 return remoteViews; 214 } 215 } 216