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.graphics.Canvas; 21 import android.graphics.Paint; 22 import android.graphics.Paint.FontMetricsInt; 23 import android.text.Spanned; 24 import android.text.TextPaint; 25 import android.text.TextUtils; 26 import android.text.style.CharacterStyle; 27 import android.text.style.ReplacementSpan; 28 29 /** 30 * A replacement span to use when displaying folders in conversation view. Prevents a folder name 31 * from wrapping mid-name, and ellipsizes very long folder names that can't fit on a single line. 32 * Also ensures that folder text is drawn vertically centered within the background color chip. 33 * 34 */ 35 public class FolderSpan extends ReplacementSpan { 36 37 public interface FolderSpanDimensions { 38 int getPadding(); 39 40 /** 41 * Returns the padding value that corresponds to the horizontal padding 42 * surrounding the text inside the background color. 43 */ 44 int getPaddingExtraWidth(); 45 46 /** 47 * Returns the padding value for the space between folders. 48 */ 49 int getPaddingBefore(); 50 51 /** 52 * Returns the spacing above each line outside of the . 53 */ 54 int getPaddingAbove(); 55 int getMaxWidth(); 56 } 57 58 private TextPaint mWorkPaint = new TextPaint(); 59 /** 60 * A reference to the enclosing Spanned object to collect other CharacterStyle spans and take 61 * them into account when drawing. 62 */ 63 private final Spanned mSpanned; 64 private final FolderSpanDimensions mDims; 65 66 public FolderSpan(Spanned spanned, FolderSpanDimensions dims) { 67 mSpanned = spanned; 68 mDims = dims; 69 } 70 71 @Override 72 public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) { 73 if (fm != null) { 74 final int paddingV = mDims.getPadding(); 75 paint.getFontMetricsInt(fm); 76 // The magic set of measurements to vertically center text within a colored region! 77 fm.ascent -= paddingV; 78 fm.top = fm.ascent; 79 fm.bottom += paddingV; 80 fm.descent += paddingV; 81 } 82 return measureWidth(paint, text, start, end, true); 83 } 84 85 private int measureWidth(Paint paint, CharSequence text, int start, int end, 86 boolean includePaddingBefore) { 87 final int paddingW = mDims.getPadding() + mDims.getPaddingExtraWidth(); 88 final int maxWidth = mDims.getMaxWidth(); 89 90 int w = (int) paint.measureText(text, start, end) + 2 * paddingW; 91 if (includePaddingBefore) { 92 w += mDims.getPaddingBefore(); 93 } 94 // TextView doesn't handle spans that are wider than the view very well, so cap their widths 95 if (w > maxWidth) { 96 w = maxWidth; 97 } 98 return w; 99 } 100 101 @Override 102 public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, 103 int y, int bottom, Paint paint) { 104 105 final int paddingW = mDims.getPadding() + mDims.getPaddingExtraWidth(); 106 final int paddingBefore = mDims.getPaddingBefore(); 107 final int paddingAbove = mDims.getPaddingAbove(); 108 final int maxWidth = mDims.getMaxWidth(); 109 110 mWorkPaint.set(paint); 111 112 // take into account the foreground/background color spans when painting 113 final CharacterStyle[] otherSpans = mSpanned.getSpans(start, end, CharacterStyle.class); 114 for (CharacterStyle otherSpan : otherSpans) { 115 otherSpan.updateDrawState(mWorkPaint); 116 } 117 118 final int bgWidth = measureWidth(mWorkPaint, text, start, end, false); 119 120 // paint a background if present 121 if (mWorkPaint.bgColor != 0) { 122 final int prevColor = mWorkPaint.getColor(); 123 final Paint.Style prevStyle = mWorkPaint.getStyle(); 124 125 mWorkPaint.setColor(mWorkPaint.bgColor); 126 mWorkPaint.setStyle(Paint.Style.FILL); 127 canvas.drawRect(x + paddingBefore, top + paddingAbove, x + bgWidth + paddingBefore, bottom, 128 mWorkPaint); 129 130 mWorkPaint.setColor(prevColor); 131 mWorkPaint.setStyle(prevStyle); 132 } 133 134 // middle-ellipsize long strings 135 if (bgWidth == maxWidth) { 136 text = TextUtils.ellipsize(text.subSequence(start, end).toString(), mWorkPaint, 137 bgWidth - 2 * paddingW, TextUtils.TruncateAt.MIDDLE); 138 start = 0; 139 end = text.length(); 140 } 141 canvas.drawText(text, start, end, x + paddingW + paddingBefore, y + paddingAbove, mWorkPaint); 142 } 143 144 } 145