1 /* 2 * Copyright (C) 2012 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.mail.browse; 19 20 import android.content.Context; 21 import android.graphics.Canvas; 22 import android.graphics.Paint; 23 import android.graphics.Paint.FontMetricsInt; 24 import android.graphics.Rect; 25 import android.graphics.drawable.Drawable; 26 import android.text.style.DynamicDrawableSpan; 27 import android.text.style.ImageSpan; 28 import android.text.style.ReplacementSpan; 29 30 import java.lang.ref.WeakReference; 31 32 /** 33 * Acts like an {@link ImageSpan}, with some important distinctions: 34 * <ol> 35 * <li>modifies font metrics in a manner consistent with {@link FolderSpan} 36 * (will not increase line height beyond {@link FolderSpan} height)</li> 37 * <li>draws its image vertically centered within its line</li> 38 * <li>allows horizontal and vertical padding</li> 39 * </ol> 40 * Much of this code was copied from {@link DynamicDrawableSpan} and ImageSpan 41 * because 42 * {@link DynamicDrawableSpan#draw(Canvas, CharSequence, int, int, float, int, int, int, Paint)} 43 * is difficult to override efficiently owing to the private getCachedDrawable() 44 * method (filed as bug 5354674). 45 */ 46 public class PriorityIndicatorSpan extends ReplacementSpan { 47 48 private final Context mContext; 49 private final int mResId; 50 private final int mPaddingV; 51 private final int mPaddingH; 52 private final int mPaddingAbove; 53 54 private WeakReference<Drawable> mDrawableRef; 55 56 public PriorityIndicatorSpan(Context context, int resId, int paddingV, int paddingH, 57 int paddingAbove) { 58 mContext = context; 59 mResId = resId; 60 mPaddingV = paddingV; 61 mPaddingH = paddingH; 62 mPaddingAbove = paddingAbove; 63 } 64 65 private Drawable getDrawable() { 66 Drawable d = mContext.getResources().getDrawable(mResId); 67 d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); 68 return d; 69 } 70 71 private Drawable getCachedDrawable() { 72 WeakReference<Drawable> wr = mDrawableRef; 73 Drawable d = null; 74 75 if (wr != null) 76 d = wr.get(); 77 78 if (d == null) { 79 d = getDrawable(); 80 mDrawableRef = new WeakReference<Drawable>(d); 81 } 82 83 return d; 84 } 85 86 @Override 87 public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) { 88 Drawable d = getCachedDrawable(); 89 Rect rect = d.getBounds(); 90 91 if (fm != null) { 92 paint.getFontMetricsInt(fm); 93 fm.ascent -= mPaddingV; 94 fm.top = fm.ascent; 95 fm.bottom += mPaddingV; 96 fm.descent += mPaddingV; 97 } 98 99 return rect.right + 2 * mPaddingH; 100 } 101 102 @Override 103 public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, 104 int y, int bottom, Paint paint) { 105 Drawable b = getCachedDrawable(); 106 canvas.save(); 107 108 final int transY = (top + bottom + mPaddingAbove - b.getBounds().bottom) / 2; 109 110 canvas.translate(x + mPaddingH, transY); 111 b.draw(canvas); 112 canvas.restore(); 113 } 114 115 } 116