Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a2ab617 authored by Robyn Coultas's avatar Robyn Coultas
Browse files

Change Counting Digits to Thin Font

Change-Id: I0dfea1e81c8810115212f599426e3141095c7b87
parent 4b4c36c4
Loading
Loading
Loading
Loading
+74 −58
Original line number Diff line number Diff line
@@ -33,32 +33,37 @@ import com.android.deskclock.R;
import com.android.deskclock.Utils;


/**
 * Class to measure and draw the time in the {@link com.android.deskclock.CircleTimerView}.
 * This class manages and sums the work of the four members mBigHours, mBigMinutes,
 * mBigSeconds and mMedHundredths. Those members are each tasked with measuring, sizing and
 * drawing digits (and optional label) of the time set in {@link #setTime(long, boolean, boolean)}
 */
public class CountingTimerView extends View {
    private static final String TWO_DIGITS = "%02d";
    private static final String ONE_DIGIT = "%01d";
    private static final String NEG_TWO_DIGITS = "-%02d";
    private static final String NEG_ONE_DIGIT = "-%01d";
    private static final float TEXT_SIZE_TO_WIDTH_RATIO = 0.75f;
    // This is the ratio of the font typeface we need to offset the font by vertically to align it
    // vertically center.
    // This is the ratio of the font height needed to vertically offset the font for alignment
    // from the center.
    private static final float FONT_VERTICAL_OFFSET = 0.14f;

    private String mHours, mMinutes, mSeconds, mHundredths;

    private boolean mShowTimeStr = true;
    private final Typeface mAndroidClockMonoThin, mAndroidClockMonoBold, mAndroidClockMonoLight;
    private final Typeface mRobotoLabel;
    private final Paint mPaintBig = new Paint();
    private final Paint mPaintBigThin = new Paint();
    private final Paint mPaintMed = new Paint();
    private final Paint mPaintLabel = new Paint();
    private final float mBigFontSize, mSmallFontSize;
    // Hours and minutes are signed for when a timer goes past the set time and thus negative
    private final SignedTime mBigHours, mBigMinutes;
    private final UnsignedTime mBigThinSeconds;
    // Seconds are always shown with minutes, so are never signed
    private final UnsignedTime mBigSeconds;
    private final Hundredths mMedHundredths;
    private float mTextHeight = 0;
    private float mTotalTextWidth;
    private static final String HUNDREDTH_SEPERATOR = ".";
    private static final String HUNDREDTH_SEPARATOR = ".";
    private boolean mRemeasureText = true;

    private int mDefaultColor;
@@ -83,6 +88,11 @@ public class CountingTimerView extends View {

    };

    /**
     * Class to measure and draw the digit pairs of hours, minutes, seconds or hundredths. Digits
     * may have an optional label. for hours, minutes and seconds, this label trails the digits
     * and for seconds, precedes the digits.
     */
    class UnsignedTime {
        protected Paint mPaint;
        protected float mEm;
@@ -169,6 +179,9 @@ public class CountingTimerView extends View {
        }
    }

    /**
     * Special derivation to handle the hundredths painting with the label in front.
     */
    class Hundredths extends UnsignedTime {
        public Hundredths(Paint paint, final String label, final String allDigits) {
            super(paint, label, allDigits);
@@ -183,15 +196,14 @@ public class CountingTimerView extends View {
        }
    }

    /**
     * Special derivation to handle a negative number
     */
    class SignedTime extends UnsignedTime {
        private float mMinusWidth = 0;

        public SignedTime(Paint paint, final String label, final String allDigits) {
            super(paint, label, allDigits);
        }

        public SignedTime (SignedTime signedTime, final String label) {
            super(signedTime, label);
        public SignedTime (UnsignedTime unsignedTime, final String label) {
            super(unsignedTime, label);
        }

        @Override
@@ -217,7 +229,7 @@ public class CountingTimerView extends View {
            if (mMinusWidth != 0f) {
                float minusWidth = mMinusWidth / 2;
                x += minusWidth;
                canvas.drawText(time.substring(ii, ii + 1), x, y, mPaint);
                canvas.drawText(time.substring(0, 1), x, y, mPaint);
                x += minusWidth;
                ii++;
            }
@@ -229,48 +241,42 @@ public class CountingTimerView extends View {
        }
    }

    @SuppressWarnings("unused")
    public CountingTimerView(Context context) {
        this(context, null);
    }

    public CountingTimerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mAndroidClockMonoThin = Typeface.createFromAsset(
                context.getAssets(), "fonts/AndroidClockMono-Thin.ttf");
        mAndroidClockMonoBold = Typeface.createFromAsset(
                context.getAssets(), "fonts/AndroidClockMono-Bold.ttf");
        mAndroidClockMonoLight = Typeface.createFromAsset(
                context.getAssets(), "fonts/AndroidClockMono-Light.ttf");
        mAccessibilityManager =
                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
        mRobotoLabel= Typeface.create("sans-serif-condensed", Typeface.BOLD);
        Resources r = context.getResources();
        mWhiteColor = r.getColor(R.color.clock_white);
        mDefaultColor = mWhiteColor;
        mPressedColor = r.getColor(Utils.getPressedColorId());
        mRedColor = r.getColor(R.color.clock_red);

        mPaintBig.setAntiAlias(true);
        mPaintBig.setStyle(Paint.Style.STROKE);
        mPaintBig.setTextAlign(Paint.Align.CENTER);
        mPaintBig.setTypeface(mAndroidClockMonoBold);
        mBigFontSize = r.getDimension(R.dimen.big_font_size);
        mSmallFontSize = r.getDimension(R.dimen.small_font_size);

        Typeface androidClockMonoThin = Typeface.
                createFromAsset(context.getAssets(), "fonts/AndroidClockMono-Thin.ttf");
        mPaintBigThin.setAntiAlias(true);
        mPaintBigThin.setStyle(Paint.Style.STROKE);
        mPaintBigThin.setTextAlign(Paint.Align.CENTER);
        mPaintBigThin.setTypeface(mAndroidClockMonoThin);
        mPaintBigThin.setTypeface(androidClockMonoThin);

        Typeface androidClockMonoLight = Typeface.
                createFromAsset(context.getAssets(), "fonts/AndroidClockMono-Light.ttf");
        mPaintMed.setAntiAlias(true);
        mPaintMed.setStyle(Paint.Style.STROKE);
        mPaintMed.setTextAlign(Paint.Align.CENTER);
        mPaintMed.setTypeface(mAndroidClockMonoLight);
        mPaintMed.setTypeface(androidClockMonoLight);

        Typeface robotoLabel = Typeface.create("sans-serif-condensed", Typeface.BOLD);
        mPaintLabel.setAntiAlias(true);
        mPaintLabel.setStyle(Paint.Style.STROKE);
        mPaintLabel.setTextAlign(Paint.Align.LEFT);
        mPaintLabel.setTypeface(mRobotoLabel);
        mPaintLabel.setTypeface(robotoLabel);
        mPaintLabel.setTextSize(r.getDimension(R.dimen.label_font_size));

        resetTextSize();
@@ -278,32 +284,39 @@ public class CountingTimerView extends View {

        // allDigits will contain ten digits: "0123456789" in the default locale
        final String allDigits = String.format("%010d", 123456789);
        mBigHours = new SignedTime(mPaintBig,
                r.getString(R.string.hours_label).toUpperCase(), allDigits);
        mBigMinutes = new SignedTime(mBigHours,
                r.getString(R.string.minutes_label).toUpperCase());
        mBigThinSeconds = new UnsignedTime(mPaintBigThin,
        mBigSeconds = new UnsignedTime(mPaintBigThin,
                r.getString(R.string.seconds_label).toUpperCase(), allDigits);
        mMedHundredths = new Hundredths(mPaintMed, HUNDREDTH_SEPERATOR, allDigits);
        mBigHours = new SignedTime(mBigSeconds, r.getString(R.string.hours_label).toUpperCase());
        mBigMinutes = new SignedTime(mBigSeconds, r.getString(R.string.minutes_label).toUpperCase());
        mMedHundredths = new Hundredths(mPaintMed, HUNDREDTH_SEPARATOR, allDigits);
    }

    protected void resetTextSize() {
        mPaintBig.setTextSize(mBigFontSize);
        mTextHeight = mBigFontSize;
        mPaintBigThin.setTextSize(mBigFontSize);
        mPaintMed.setTextSize(mSmallFontSize);
    }

    protected void setTextColor(int textColor) {
        mPaintBig.setColor(textColor);
        mPaintBigThin.setColor(textColor);
        mPaintMed.setColor(textColor);
        mPaintLabel.setColor(textColor);
    }

    /**
     * Update the time to display. Separates that time into the hours, minutes, seconds and
     * hundredths. If update is true, the view is invalidated so that it will draw again.
     *
     * @param time new time to display - in milliseconds
     * @param showHundredths flag to show hundredths resolution
     * @param update to invalidate the view - otherwise the time is examined to see if it is within
     *               100 milliseconds of zero seconds and when so, invalidate the view.
     */
    // TODO(coultasr):showHundredths S/B attribute or setter - i.e. unchanging over object life
    public void setTime(long time, boolean showHundredths, boolean update) {
        int oldLength = getDigitsLength();
        boolean neg = false, showNeg = false;
        String format = null;
        String format;
        if (time < 0) {
            time = -time;
            neg = showNeg = true;
@@ -318,12 +331,15 @@ public class CountingTimerView extends View {
        if (hours > 999) {
            hours = 0;
        }
        // time may less than a second below zero, since we do not show fractions of seconds
        // The time  can be between 0 and -1 seconds, but the "truncated" equivalent time of hours
        // and minutes and seconds could be zero, so since we do not show fractions of seconds
        // when counting down, do not show the minus sign.
        // TODO(coultasr):does that matter that we do nto look at showHundredths?
        if (hours == 0 && minutes == 0 && seconds == 0) {
            showNeg = false;
        }

        // Normalize and check if it is 'time' to invalidate
        if (!showHundredths) {
            if (!neg && hundreds != 0) {
                seconds++;
@@ -341,8 +357,7 @@ public class CountingTimerView extends View {
            }
        }

        int oldLength = getDigitsLength();

        // Hours may be empty
        if (hours >= 10) {
            format = showNeg ? NEG_TWO_DIGITS : TWO_DIGITS;
            mHours = String.format(format, hours);
@@ -353,6 +368,7 @@ public class CountingTimerView extends View {
            mHours = null;
        }

        // Minutes are never empty and when hours are non-empty, must be two digits
        if (minutes >= 10 || hours > 0) {
            format = (showNeg && hours == 0) ? NEG_TWO_DIGITS : TWO_DIGITS;
            mMinutes = String.format(format, minutes);
@@ -361,7 +377,10 @@ public class CountingTimerView extends View {
            mMinutes = String.format(format, minutes);
        }

        // Seconds are always two digits
        mSeconds = String.format(TWO_DIGITS, seconds);

        // Hundredths are optional and then two digits
        if (showHundredths) {
            mHundredths = String.format(TWO_DIGITS, hundreds);
        } else {
@@ -392,7 +411,7 @@ public class CountingTimerView extends View {

    private void calcTotalTextWidth() {
        mTotalTextWidth = mBigHours.calcTotalWidth(mHours) + mBigMinutes.calcTotalWidth(mMinutes)
                + mBigThinSeconds.calcTotalWidth(mSeconds)
                + mBigSeconds.calcTotalWidth(mSeconds)
                + mMedHundredths.calcTotalWidth(mHundredths);
    }

@@ -408,20 +427,19 @@ public class CountingTimerView extends View {
            while (mTotalTextWidth > wantWidth) {
                // Get fixed and variant parts of the total size
                float fixedWidths = mBigHours.getLabelWidth() + mBigMinutes.getLabelWidth()
                        + mBigThinSeconds.getLabelWidth() + mMedHundredths.getLabelWidth();
                        + mBigSeconds.getLabelWidth() + mMedHundredths.getLabelWidth();
                float varWidths = mBigHours.getWidth() + mBigMinutes.getWidth()
                        + mBigThinSeconds.getWidth() + mMedHundredths.getWidth();
                        + mBigSeconds.getWidth() + mMedHundredths.getWidth();
                // Avoid divide by zero || sizeRatio == 1 || sizeRatio <= 0
                if (varWidths == 0 || fixedWidths == 0 || fixedWidths >= wantWidth) {
                    break;
                }
                // Variant-section reduction
                float sizeRatio = (wantWidth - fixedWidths) / varWidths;
                mPaintBig.setTextSize(mPaintBig.getTextSize() * sizeRatio);
                mPaintBigThin.setTextSize(mPaintBigThin.getTextSize() * sizeRatio);
                mPaintMed.setTextSize(mPaintMed.getTextSize() * sizeRatio);
                //recalculate the new total text width and half text height
                mTextHeight = mPaintBig.getTextSize();
                // Recalculate the new total text height and half-width
                mTextHeight = mPaintBigThin.getTextSize();
                calcTotalTextWidth();
            }
        }
@@ -583,10 +601,10 @@ public class CountingTimerView extends View {
        int xCenter = width / 2;
        int yCenter = getHeight() / 2;

        float textXstart = xCenter - mTotalTextWidth / 2;
        float textYstart = yCenter + mTextHeight/2 - (mTextHeight * FONT_VERTICAL_OFFSET);
        float xTextStart = xCenter - mTotalTextWidth / 2;
        float yTextStart = yCenter + mTextHeight/2 - (mTextHeight * FONT_VERTICAL_OFFSET);
        // align the labels vertically to the top of the rest of the text
        float labelYStart = textYstart - (mTextHeight * (1 - 2 * FONT_VERTICAL_OFFSET))
        float labelYStart = yTextStart - (mTextHeight * (1 - 2 * FONT_VERTICAL_OFFSET))
                + (1 - 2 * FONT_VERTICAL_OFFSET) * mPaintLabel.getTextSize();

        // Text color differs based on pressed state.
@@ -597,24 +615,22 @@ public class CountingTimerView extends View {
        } else {
            textColor = mDefaultColor;
        }
        mPaintBig.setColor(textColor);
        mPaintBigThin.setColor(textColor);
        mPaintLabel.setColor(textColor);
        mPaintMed.setColor(textColor);

        if (mHours != null) {
            textXstart = mBigHours.draw(canvas, mHours, textXstart, textYstart, labelYStart);
            xTextStart = mBigHours.draw(canvas, mHours, xTextStart, yTextStart, labelYStart);
        }
        if (mMinutes != null) {
            textXstart = mBigMinutes.draw(canvas, mMinutes, textXstart, textYstart, labelYStart);
            xTextStart = mBigMinutes.draw(canvas, mMinutes, xTextStart, yTextStart, labelYStart);
        }
        if (mSeconds != null) {
            textXstart = mBigThinSeconds.draw(canvas, mSeconds,
                    textXstart, textYstart, labelYStart);
            xTextStart = mBigSeconds.
                    draw(canvas, mSeconds, xTextStart, yTextStart, labelYStart);
        }
        if (mHundredths != null) {
            textXstart = mMedHundredths.draw(canvas, mHundredths,
                    textXstart, textYstart, textYstart);
            mMedHundredths.draw(canvas, mHundredths, xTextStart, yTextStart, yTextStart);
        }
    }