/* * 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; import static android.graphics.Typeface.BOLD; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.BackgroundColorSpan; import android.text.style.ForegroundColorSpan; import android.text.style.StyleSpan; import android.text.style.TypefaceSpan; import android.text.style.URLSpan; import android.view.View; import android.view.View.OnClickListener; import com.github.mobile.util.TimeUtils; import java.util.Date; import java.util.Locale; /** * Helpers on top of {@link SpannableStringBuilder} */ public class StyledText extends SpannableStringBuilder { /** * Append text and span to end of this text * * @param text * @param span * @return this text */ public StyledText append(final CharSequence text, final Object span) { if (!TextUtils.isEmpty(text)) { append(text); if (span != null) { final int length = length(); setSpan(span, length - text.length(), length, SPAN_EXCLUSIVE_EXCLUSIVE); } } return this; } @Override public StyledText append(char text) { super.append(text); return this; } @Override public StyledText append(CharSequence text) { if (text != null) super.append(text); return this; } /** * Append text and span to end of this text * * @param text * @param span * @return this text */ public StyledText append(final char text, final Object span) { append(text); if (span != null) { final int length = length(); setSpan(span, length - 1, length, SPAN_EXCLUSIVE_EXCLUSIVE); } return this; } /** * Append text in bold * * @param text * @return this text */ public StyledText bold(final CharSequence text) { return append(text, new StyleSpan(BOLD)); } /** * Append text in bold * * @param text * @param color * @return this text */ public StyledText background(final CharSequence text, final int color) { return append(text, new BackgroundColorSpan(color)); } /** * Append text in with custom foreground color * * @param text * @param color * @return this text */ public StyledText foreground(final CharSequence text, final int color) { return append(text, new ForegroundColorSpan(color)); } /** * Append text in with custom foreground color * * @param text * @param color * @return this text */ public StyledText foreground(final char text, final int color) { return append(text, new ForegroundColorSpan(color)); } /** * Append text in monospace typeface * * @param text * @return this text */ public StyledText monospace(final CharSequence text) { return append(text, new TypefaceSpan("monospace")); } /** * Append text as URL * * @param text * @param listener * @return this text */ public StyledText url(final CharSequence text, final OnClickListener listener) { return append(text, new URLSpan(text.toString()) { @Override public void onClick(View widget) { listener.onClick(widget); } }); } /** * Append text as URL * * @param text * @return this text */ public StyledText url(final CharSequence text) { return append(text, new URLSpan(text.toString())); } /** * Append given date in relative time format * * @param date * @return this text */ public StyledText append(final Date date) { final CharSequence time = TimeUtils.getRelativeTime(date); // Un-capitalize time string if there is already a prefix. // So you get "opened in 5 days" instead of "opened In 5 days". final int timeLength = time.length(); if (length() > 0 && timeLength > 0 && Character.isUpperCase(time.charAt(0))) { append(time.subSequence(0, 1).toString() .toLowerCase(Locale.getDefault())); append(time.subSequence(1, timeLength)); } else append(time); return this; } }