/* * Copyright 2012 GitHub Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.mobile.ui.issue; import static android.graphics.Color.WHITE; import static android.graphics.Typeface.DEFAULT_BOLD; import static java.lang.Integer.MIN_VALUE; import static java.lang.String.CASE_INSENSITIVE_ORDER; import static java.util.Locale.US; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.PaintDrawable; import android.text.style.DynamicDrawableSpan; import android.widget.TextView; import com.github.mobile.R.drawable; import com.github.mobile.R.id; import com.github.mobile.ui.StyledText; import com.github.mobile.util.ServiceUtils; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import org.eclipse.egit.github.core.Label; /** * Span that draws a {@link Label} */ public class LabelDrawableSpan extends DynamicDrawableSpan { private static final int PADDING_LEFT = 10; private static final int PADDING_RIGHT = 10; private static final int PADDING_TOP = 8; private static final int PADDING_BOTTOM = 8; private static class LabelDrawable extends PaintDrawable { private final String name; private final float height; private final float paddingLeft; private final float textHeight; private final int textColor; private final LayerDrawable layers; /** * Create drawable for labels * * @param paddingLeft * @param textHeight * @param bounds * @param resources * @param textSize * @param name * @param bg */ public LabelDrawable(final float paddingLeft, final float textHeight, final Rect bounds, final Resources resources, final float textSize, final String name, final int bg) { this.paddingLeft = paddingLeft; this.textHeight = textHeight; this.name = name; height = bounds.height(); float[] hsv = new float[3]; Color.colorToHSV(bg, hsv); if ((hsv[2] > 0.6 && hsv[1] < 0.4) || (hsv[2] > 0.7 && hsv[0] > 40 && hsv[0] < 200)) { hsv[2] = 0.4F; textColor = Color.HSVToColor(hsv); } else textColor = WHITE; layers = (LayerDrawable) resources .getDrawable(drawable.label_background); ((GradientDrawable) ((LayerDrawable) layers .findDrawableByLayerId(id.item_outer_layer)) .findDrawableByLayerId(id.item_outer)).setColor(bg); ((GradientDrawable) ((LayerDrawable) layers .findDrawableByLayerId(id.item_inner_layer)) .findDrawableByLayerId(id.item_inner)).setColor(bg); ((GradientDrawable) layers.findDrawableByLayerId(id.item_bg)) .setColor(bg); Paint p = getPaint(); p.setAntiAlias(true); p.setColor(resources.getColor(android.R.color.transparent)); p.setTypeface(DEFAULT_BOLD); p.setTextSize(textSize); layers.setBounds(bounds); setBounds(bounds); } @Override public void draw(final Canvas canvas) { super.draw(canvas); layers.draw(canvas); final Paint paint = getPaint(); final int original = paint.getColor(); paint.setColor(textColor); canvas.drawText(name, paddingLeft, height - ((height - textHeight) / 2), paint); paint.setColor(original); } } /** * Set text on view to be given labels * * @param view * @param labels */ public static void setText(final TextView view, final Collection<Label> labels) { final Label[] sortedLabels = labels.toArray(new Label[labels.size()]); Arrays.sort(sortedLabels, new Comparator<Label>() { @Override public int compare(final Label lhs, final Label rhs) { return CASE_INSENSITIVE_ORDER.compare(lhs.getName(), rhs.getName()); } }); setText(view, sortedLabels); } /** * Set text on view to be given label * * @param view * @param label */ public static void setText(final TextView view, final Label label) { setText(view, new Label[] { label }); } private static void setText(final TextView view, final Label[] labels) { final Resources resources = view.getResources(); final float paddingTop = ServiceUtils.getPixels(resources, PADDING_TOP); final float paddingLeft = ServiceUtils.getPixels(resources, PADDING_LEFT); final float paddingRight = ServiceUtils.getPixels(resources, PADDING_RIGHT); final float paddingBottom = ServiceUtils.getPixels(resources, PADDING_BOTTOM); Paint p = new Paint(); p.setTypeface(DEFAULT_BOLD); p.setTextSize(view.getTextSize()); final Rect textBounds = new Rect(); String[] names = new String[labels.length]; int[] nameWidths = new int[labels.length]; int textHeight = MIN_VALUE; for (int i = 0; i < labels.length; i++) { String name = labels[i].getName().toUpperCase(US); textBounds.setEmpty(); p.getTextBounds(name, 0, name.length(), textBounds); names[i] = name; textHeight = Math.max(textBounds.height(), textHeight); nameWidths[i] = textBounds.width(); } final float textSize = view.getTextSize(); final StyledText text = new StyledText(); for (int i = 0; i < labels.length; i++) { Rect bounds = new Rect(); bounds.right = Math.round(nameWidths[i] + paddingLeft + paddingRight + 0.5F); bounds.bottom = Math.round(textHeight + paddingTop + paddingBottom + 0.5F); text.append('\uFFFC', new LabelDrawableSpan(resources, textSize, labels[i].getColor(), paddingLeft, textHeight, bounds, names[i])); if (i + 1 < labels.length) text.append(' '); } view.setText(text); } private final Resources resources; private final float textSize; private final String name; private final int color; private final float textHeight; private final float paddingLeft; private final Rect bounds; /** * Create background span for label * * @param resources * @param textSize * @param color * @param paddingLeft * @param textHeight * @param bounds * @param name */ public LabelDrawableSpan(final Resources resources, final float textSize, final String color, final float paddingLeft, final float textHeight, final Rect bounds, final String name) { this.resources = resources; this.textSize = textSize; this.color = Color.parseColor('#' + color); this.paddingLeft = paddingLeft; this.textHeight = textHeight; this.bounds = bounds; this.name = name; } @Override public Drawable getDrawable() { return new LabelDrawable(paddingLeft, textHeight, bounds, resources, textSize, name, color); } }