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 17package com.android.mail.widget; 18 19import android.content.Context; 20import android.content.res.Resources; 21import android.graphics.Bitmap; 22import android.graphics.BitmapFactory; 23import android.graphics.Typeface; 24import android.text.Spannable; 25import android.text.SpannableStringBuilder; 26import android.text.style.AbsoluteSizeSpan; 27import android.text.style.CharacterStyle; 28import android.text.style.ForegroundColorSpan; 29import android.text.style.StyleSpan; 30import android.view.View; 31import android.widget.RemoteViews; 32 33import com.android.mail.R; 34import com.android.mail.providers.Conversation; 35import com.android.mail.providers.Folder; 36import com.android.mail.ui.FolderDisplayer; 37import com.android.mail.utils.FolderUri; 38 39public 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[] {folderValues.getBackgroundColor(mDefaultBgColor)}; 96 Bitmap bitmap = Bitmap.createBitmap(color, 1, 1, Bitmap.Config.RGB_565); 97 remoteViews.setImageViewBitmap(viewId, bitmap); 98 99 if (++displayedFolder == MAX_DISPLAYED_FOLDERS_COUNT) { 100 break; 101 } 102 } 103 104 for (int i = displayedFolder; i < MAX_DISPLAYED_FOLDERS_COUNT; i++) { 105 remoteViews.setViewVisibility(getFolderViewId(i), View.GONE); 106 } 107 } 108 } 109 110 /* 111 * Get font sizes and bitmaps from Resources 112 */ 113 public WidgetConversationListItemViewBuilder(Context context) { 114 final Resources res = context.getResources(); 115 116 // Initialize colors 117 SUBJECT_TEXT_COLOR_READ = res.getColor(R.color.subject_text_color_read); 118 SUBJECT_TEXT_COLOR_UNREAD = res.getColor(R.color.subject_text_color_unread); 119 SNIPPET_TEXT_COLOR = res.getColor(R.color.snippet_text_color); 120 DATE_TEXT_COLOR_READ = res.getColor(R.color.date_text_color_read); 121 DATE_TEXT_COLOR_UNREAD = res.getColor(R.color.date_text_color_unread); 122 123 // Initialize Bitmap 124 ATTACHMENT = BitmapFactory.decodeResource(res, R.drawable.ic_attach_file_20dp); 125 } 126 127 /* 128 * Add size, color and style to a given text 129 */ 130 private static CharSequence addStyle(CharSequence text, int size, int color) { 131 SpannableStringBuilder builder = new SpannableStringBuilder(text); 132 builder.setSpan( 133 new AbsoluteSizeSpan(size), 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 134 if (color != 0) { 135 builder.setSpan(new ForegroundColorSpan(color), 0, text.length(), 136 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 137 } 138 return builder; 139 } 140 141 /* 142 * Return the full View 143 */ 144 public RemoteViews getStyledView(final Context context, final CharSequence date, 145 final Conversation conversation, final FolderUri folderUri, final int ignoreFolderType, 146 final SpannableStringBuilder senders, String subject) { 147 148 final boolean isUnread = !conversation.read; 149 final String snippet = conversation.getSnippet(); 150 final boolean hasAttachments = conversation.hasAttachments; 151 final Resources res = context.getResources(); 152 final int dateFontSize = res.getDimensionPixelSize(R.dimen.widget_date_font_size); 153 final int subjectFontSize = res.getDimensionPixelSize(R.dimen.widget_subject_font_size); 154 155 // Add style to date 156 final int dateColor = isUnread ? DATE_TEXT_COLOR_UNREAD : DATE_TEXT_COLOR_READ; 157 final CharSequence styledDate = addStyle(date, dateFontSize, dateColor); 158 159 subject = Conversation.getSubjectForDisplay(context, null /* badgeText */, subject); 160 final SpannableStringBuilder subjectBuilder = new SpannableStringBuilder(subject); 161 if (isUnread) { 162 subjectBuilder.setSpan(new StyleSpan(Typeface.BOLD), 0, subject.length(), 163 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 164 } 165 final CharacterStyle subjectStyle = new ForegroundColorSpan( 166 isUnread ? SUBJECT_TEXT_COLOR_UNREAD : SUBJECT_TEXT_COLOR_READ); 167 subjectBuilder.setSpan(subjectStyle, 0, subjectBuilder.length(), 168 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 169 final CharSequence styledSubject = addStyle(subjectBuilder, subjectFontSize, 0); 170 171 final SpannableStringBuilder snippetBuilder = new SpannableStringBuilder(snippet); 172 snippetBuilder.setSpan(new ForegroundColorSpan(SNIPPET_TEXT_COLOR), 0, 173 snippetBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 174 final CharSequence styledSnippet = addStyle(snippetBuilder, subjectFontSize, 0); 175 176 // Paper clip for attachment 177 Bitmap paperclipBitmap = null; 178 if (hasAttachments) { 179 paperclipBitmap = ATTACHMENT; 180 } 181 182 // Inflate and fill out the remote view 183 final RemoteViews remoteViews = new RemoteViews( 184 context.getPackageName(), R.layout.widget_conversation_list_item); 185 remoteViews.setTextViewText(R.id.widget_senders, senders); 186 remoteViews.setTextViewText(R.id.widget_date, styledDate); 187 remoteViews.setTextViewText(R.id.widget_subject, styledSubject); 188 remoteViews.setTextViewText(R.id.widget_snippet, styledSnippet); 189 if (paperclipBitmap != null) { 190 remoteViews.setViewVisibility(R.id.widget_attachment, View.VISIBLE); 191 remoteViews.setImageViewBitmap(R.id.widget_attachment, paperclipBitmap); 192 } else { 193 remoteViews.setViewVisibility(R.id.widget_attachment, View.GONE); 194 } 195 if (isUnread) { 196 remoteViews.setViewVisibility(R.id.widget_unread_background, View.VISIBLE); 197 remoteViews.setViewVisibility(R.id.widget_read_background, View.GONE); 198 } else { 199 remoteViews.setViewVisibility(R.id.widget_unread_background, View.GONE); 200 remoteViews.setViewVisibility(R.id.widget_read_background, View.VISIBLE); 201 } 202 if (context.getResources().getBoolean(R.bool.display_folder_colors_in_widget)) { 203 mFolderDisplayer = new WidgetFolderDisplayer(context); 204 mFolderDisplayer.loadConversationFolders(conversation, folderUri, ignoreFolderType); 205 mFolderDisplayer.displayFolders(remoteViews); 206 } 207 208 return remoteViews; 209 } 210} 211