• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
getPadding()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          */
getPaddingExtraWidth()44         int getPaddingExtraWidth();
45 
46         /**
47          * Returns the padding value for the space between folders.
48          */
getPaddingBefore()49         int getPaddingBefore();
50 
51         /**
52          * Returns the spacing above each line outside of the .
53          */
getPaddingAbove()54         int getPaddingAbove();
getMaxWidth()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 
FolderSpan(Spanned spanned, FolderSpanDimensions dims)66     public FolderSpan(Spanned spanned, FolderSpanDimensions dims) {
67         mSpanned = spanned;
68         mDims = dims;
69     }
70 
71     @Override
getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm)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 
measureWidth(Paint paint, CharSequence text, int start, int end, boolean includePaddingBefore)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
draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint)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