/*
* 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);
}
}