14243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson/* 24243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * Copyright (C) 2008 The Android Open Source Project 34243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * 44243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * Licensed under the Apache License, Version 2.0 (the "License"); 54243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * you may not use this file except in compliance with the License. 64243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * You may obtain a copy of the License at 74243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * 84243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * http://www.apache.org/licenses/LICENSE-2.0 94243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * 104243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * Unless required by applicable law or agreed to in writing, software 114243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * distributed under the License is distributed on an "AS IS" BASIS, 124243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * See the License for the specific language governing permissions and 144243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson * limitations under the License. 154243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson */ 164243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 174243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelsonpackage com.android.deskclock.timer; 184243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 194243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelsonimport android.content.Context; 204243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelsonimport android.content.res.Resources; 214243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelsonimport android.graphics.Canvas; 224243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelsonimport android.graphics.Paint; 234243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelsonimport android.graphics.Typeface; 244243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelsonimport android.util.AttributeSet; 25e40b31200dee36341e5697b2774799555ca79c9bSara Tingimport android.view.MotionEvent; 264243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelsonimport android.view.View; 27932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Tingimport android.view.accessibility.AccessibilityManager; 28386d8b05069c95899149c4b18542fc18c3761314Sam Blitzsteinimport android.widget.TextView; 294243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 30357497c341662c56945e22e458852f52a977efdfSam Blitzsteinimport com.android.deskclock.DeskClock; 314243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelsonimport com.android.deskclock.R; 320f6e3350fed144e3909ba4e45f3006f042c0187cSam Blitzsteinimport com.android.deskclock.Utils; 334243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 344243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 354243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelsonpublic class CountingTimerView extends View { 364243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private static final String TWO_DIGITS = "%02d"; 374243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private static final String ONE_DIGIT = "%01d"; 384243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private static final String NEG_TWO_DIGITS = "-%02d"; 394243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private static final String NEG_ONE_DIGIT = "-%01d"; 40c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee private static final float TEXT_SIZE_TO_WIDTH_RATIO = 0.75f; 41c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee // This is the ratio of the font typeface we need to offset the font by vertically to align it 42c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee // vertically center. 43c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee private static final float FONT_VERTICAL_OFFSET = 0.14f; 444243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 454243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private String mHours, mMinutes, mSeconds, mHunderdths; 464243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private final String mHoursLabel, mMinutesLabel, mSecondsLabel; 474243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private float mHoursWidth, mMinutesWidth, mSecondsWidth, mHundredthsWidth; 484243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private float mHoursLabelWidth, mMinutesLabelWidth, mSecondsLabelWidth, mHundredthsSepWidth; 494243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 504243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private boolean mShowTimeStr = true; 51014575aefd55845714d0a614213d432ee5d9474bItzhak Katzenelson private final Typeface mAndroidClockMonoThin, mAndroidClockMonoBold, mRobotoLabel, mAndroidClockMonoLight; 524243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private final Paint mPaintBig = new Paint(); 534243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private final Paint mPaintBigThin = new Paint(); 544243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private final Paint mPaintMed = new Paint(); 554243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private final Paint mPaintLabel = new Paint(); 56c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee private float mTextHeight = 0; 574243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private float mTotalTextWidth; 584243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private static final String HUNDREDTH_SEPERATOR = "."; 594243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private boolean mRemeasureText = true; 6022ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas 6122ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas private int mDefaultColor; 62e40b31200dee36341e5697b2774799555ca79c9bSara Ting private final int mPressedColor; 6322ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas private final int mWhiteColor; 6422ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas private final int mRedColor; 65386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein private TextView mStopStartTextView; 66932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting private final AccessibilityManager mAccessibilityManager; 67e40b31200dee36341e5697b2774799555ca79c9bSara Ting 68e40b31200dee36341e5697b2774799555ca79c9bSara Ting // Fields for the text serving as a virtual button. 69e40b31200dee36341e5697b2774799555ca79c9bSara Ting private boolean mVirtualButtonEnabled = false; 70e40b31200dee36341e5697b2774799555ca79c9bSara Ting private boolean mVirtualButtonPressedOn = false; 714243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 724243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson Runnable mBlinkThread = new Runnable() { 73386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein private boolean mVisible = true; 744243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson @Override 754243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson public void run() { 76386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein mVisible = !mVisible; 77386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein CountingTimerView.this.showTime(mVisible); 784243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson postDelayed(mBlinkThread, 500); 794243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 804243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 814243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson }; 824243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 834243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 844243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson public CountingTimerView(Context context) { 854243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson this(context, null); 864243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 874243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 884243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson public CountingTimerView(Context context, AttributeSet attrs) { 894243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson super(context, attrs); 90014575aefd55845714d0a614213d432ee5d9474bItzhak Katzenelson mAndroidClockMonoThin = Typeface.createFromAsset(context.getAssets(),"fonts/AndroidClockMono-Thin.ttf"); 91014575aefd55845714d0a614213d432ee5d9474bItzhak Katzenelson mAndroidClockMonoBold = Typeface.createFromAsset(context.getAssets(),"fonts/AndroidClockMono-Bold.ttf"); 92014575aefd55845714d0a614213d432ee5d9474bItzhak Katzenelson mAndroidClockMonoLight = Typeface.createFromAsset(context.getAssets(),"fonts/AndroidClockMono-Light.ttf"); 93932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting mAccessibilityManager = 94932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE); 954243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mRobotoLabel= Typeface.create("sans-serif-condensed", Typeface.BOLD); 964243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson Resources r = context.getResources(); 974243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHoursLabel = r.getString(R.string.hours_label).toUpperCase(); 984243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mMinutesLabel = r.getString(R.string.minutes_label).toUpperCase(); 994243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mSecondsLabel = r.getString(R.string.seconds_label).toUpperCase(); 10022ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas mWhiteColor = r.getColor(R.color.clock_white); 10122ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas mDefaultColor = mWhiteColor; 1020f6e3350fed144e3909ba4e45f3006f042c0187cSam Blitzstein mPressedColor = r.getColor(Utils.getPressedColorId()); 10322ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas mRedColor = r.getColor(R.color.clock_red); 1044243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 1054243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintBig.setAntiAlias(true); 1064243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintBig.setStyle(Paint.Style.STROKE); 1074243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintBig.setTextAlign(Paint.Align.LEFT); 108014575aefd55845714d0a614213d432ee5d9474bItzhak Katzenelson mPaintBig.setTypeface(mAndroidClockMonoBold); 109c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee float bigFontSize = r.getDimension(R.dimen.big_font_size); 110c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee mPaintBig.setTextSize(bigFontSize); 111c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee mTextHeight = bigFontSize; 11222ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas 1134243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintBigThin.setAntiAlias(true); 1144243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintBigThin.setStyle(Paint.Style.STROKE); 1154243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintBigThin.setTextAlign(Paint.Align.LEFT); 116014575aefd55845714d0a614213d432ee5d9474bItzhak Katzenelson mPaintBigThin.setTypeface(mAndroidClockMonoThin); 1174243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintBigThin.setTextSize(r.getDimension(R.dimen.big_font_size)); 1184243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 1194243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintMed.setAntiAlias(true); 1204243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintMed.setStyle(Paint.Style.STROKE); 1214243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintMed.setTextAlign(Paint.Align.LEFT); 122014575aefd55845714d0a614213d432ee5d9474bItzhak Katzenelson mPaintMed.setTypeface(mAndroidClockMonoLight); 1234243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintMed.setTextSize(r.getDimension(R.dimen.small_font_size)); 1244243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 1254243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintLabel.setAntiAlias(true); 1264243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintLabel.setStyle(Paint.Style.STROKE); 1274243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintLabel.setTextAlign(Paint.Align.LEFT); 1284243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintLabel.setTypeface(mRobotoLabel); 1294243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintLabel.setTextSize(r.getDimension(R.dimen.label_font_size)); 1304243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 13122ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas setTextColor(mDefaultColor); 13222ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas } 13322ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas 13422ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas protected void setTextColor(int textColor) { 13522ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas mPaintBig.setColor(textColor); 13622ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas mPaintBigThin.setColor(textColor); 13722ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas mPaintMed.setColor(textColor); 13822ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas mPaintLabel.setColor(textColor); 1394243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 1404243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 141644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson public void setTime(long time, boolean showHundredths, boolean update) { 142644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson boolean neg = false, showNeg = false; 1434243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson String format = null; 1444243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (time < 0) { 14531943258b338ee3a36d07ff57a6fb0f94bb3650fIsaac Katzenelson time = -time; 146644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson neg = showNeg = true; 1474243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 1484243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson long hundreds, seconds, minutes, hours; 149113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein seconds = time / 1000; 150113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein hundreds = (time - seconds * 1000) / 10; 1514243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson minutes = seconds / 60; 1524243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson seconds = seconds - minutes * 60; 1534243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson hours = minutes / 60; 1544243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson minutes = minutes - hours * 60; 1554243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (hours > 99) { 1564243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson hours = 0; 1574243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 15831943258b338ee3a36d07ff57a6fb0f94bb3650fIsaac Katzenelson // time may less than a second below zero, since we do not show fractions of seconds 15931943258b338ee3a36d07ff57a6fb0f94bb3650fIsaac Katzenelson // when counting down, do not show the minus sign. 16031943258b338ee3a36d07ff57a6fb0f94bb3650fIsaac Katzenelson if (hours ==0 && minutes == 0 && seconds == 0) { 161644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson showNeg = false; 16231943258b338ee3a36d07ff57a6fb0f94bb3650fIsaac Katzenelson } 1634243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson // TODO: must build to account for localization 16420ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein if (!showHundredths) { 16520ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein if (!neg && hundreds != 0) { 16620ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein seconds++; 16720ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein if (seconds == 60) { 16820ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein seconds = 0; 16920ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein minutes++; 17020ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein if (minutes == 60) { 17120ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein minutes = 0; 17220ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein hours++; 17320ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein } 17420ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein } 17520ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein } 17620ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein if (hundreds < 10 || hundreds > 90) { 17720ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein update = true; 17820ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein } 17920ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein } 18020ea36e23e699484aefc8706d4357266ec136da8Sam Blitzstein 1814243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (hours >= 10) { 182644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson format = showNeg ? NEG_TWO_DIGITS : TWO_DIGITS; 1834243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHours = String.format(format, hours); 1844243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } else if (hours > 0) { 185644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson format = showNeg ? NEG_ONE_DIGIT : ONE_DIGIT; 1864243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHours = String.format(format, hours); 1874243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } else { 1884243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHours = null; 1894243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 1904243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 1914243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (minutes >= 10 || hours > 0) { 192644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson format = (showNeg && hours == 0) ? NEG_TWO_DIGITS : TWO_DIGITS; 1934243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mMinutes = String.format(format, minutes); 1944243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } else { 195644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson format = (showNeg && hours == 0) ? NEG_ONE_DIGIT : ONE_DIGIT; 1964243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mMinutes = String.format(format, minutes); 1974243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 1984243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 1994243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mSeconds = String.format(TWO_DIGITS, seconds); 2004243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (showHundredths) { 2014243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHunderdths = String.format(TWO_DIGITS, hundreds); 2024243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } else { 2034243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHunderdths = null; 2044243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2054243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mRemeasureText = true; 206644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson 207644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson if (update) { 208932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting setContentDescription(getTimeStringForAccessibility((int) hours, (int) minutes, 209932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting (int) seconds, showNeg, getResources())); 210644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson invalidate(); 211644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson } 2124243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2134243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson private void setTotalTextWidth() { 2144243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mTotalTextWidth = 0; 2154243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (mHours != null) { 2164243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHoursWidth = mPaintBig.measureText(mHours); 2174243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mTotalTextWidth += mHoursWidth; 2184243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHoursLabelWidth = mPaintLabel.measureText(mHoursLabel); 2194243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mTotalTextWidth += mHoursLabelWidth; 2204243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2214243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (mMinutes != null) { 2224243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mMinutesWidth = mPaintBig.measureText(mMinutes); 2234243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mTotalTextWidth += mMinutesWidth; 2244243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mMinutesLabelWidth = mPaintLabel.measureText(mMinutesLabel); 2254243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mTotalTextWidth += mMinutesLabelWidth; 2264243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2274243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (mSeconds != null) { 2284243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mSecondsWidth = mPaintBigThin.measureText(mSeconds); 2294243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mTotalTextWidth += mSecondsWidth; 2304243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mSecondsLabelWidth = mPaintLabel.measureText(mSecondsLabel); 2314243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mTotalTextWidth += mSecondsLabelWidth; 2324243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2334243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (mHunderdths != null) { 2344243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHundredthsWidth = mPaintMed.measureText(mHunderdths); 2354243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mTotalTextWidth += mHundredthsWidth; 2364243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHundredthsSepWidth = mPaintLabel.measureText(HUNDREDTH_SEPERATOR); 2374243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mTotalTextWidth += mHundredthsSepWidth; 2384243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2394243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 2404243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson // This is a hack: if the text is too wide, reduce all the paint text sizes 241c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee // To determine the maximum width, we find the minimum of the height and width (since the 242c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee // circle we are trying to fit the text into has its radius sized to the smaller of the 243c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee // two. 244c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee int width = Math.min(getWidth(), getHeight()); 2454243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (width != 0) { 2464243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson float ratio = mTotalTextWidth / width; 2474243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (ratio > TEXT_SIZE_TO_WIDTH_RATIO) { 2484243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson float sizeRatio = (TEXT_SIZE_TO_WIDTH_RATIO / ratio); 2494243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintBig.setTextSize( mPaintBig.getTextSize() * sizeRatio); 2504243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintBigThin.setTextSize( mPaintBigThin.getTextSize() * sizeRatio); 2514243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mPaintMed.setTextSize( mPaintMed.getTextSize() * sizeRatio); 2524243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mTotalTextWidth *= sizeRatio; 2534243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mMinutesWidth *= sizeRatio; 2544243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHoursWidth *= sizeRatio; 2554243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mSecondsWidth *= sizeRatio; 2564243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHundredthsWidth *= sizeRatio; 2574243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mHundredthsSepWidth *= sizeRatio; 258c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee //recalculate the new total text width and half text height 259c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee mTotalTextWidth = mHoursWidth + mMinutesWidth + mSecondsWidth + 260c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee mHundredthsWidth + mHundredthsSepWidth + mHoursLabelWidth + 261c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee mMinutesLabelWidth + mSecondsLabelWidth; 262c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee mTextHeight = mPaintBig.getTextSize(); 2634243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2644243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2654243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2664243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 2674243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson public void blinkTimeStr(boolean blink) { 2684243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (blink) { 2694243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson removeCallbacks(mBlinkThread); 2704243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson postDelayed(mBlinkThread, 1000); 2714243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } else { 2724243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson removeCallbacks(mBlinkThread); 273386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein showTime(true); 2744243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2754243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2764243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 277386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein public void showTime(boolean visible) { 278386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein mShowTimeStr = visible; 279386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein invalidate(); 280386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein mRemeasureText = true; 281386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein } 282386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein 28322ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas public void redTimeStr(boolean red, boolean forceUpdate) { 28422ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas mDefaultColor = red ? mRedColor : mWhiteColor; 28522ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas setTextColor(mDefaultColor); 28622ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas if (forceUpdate) { 28722ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas invalidate(); 28822ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas } 28922ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas } 29022ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas 2914243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson public String getTimeString() { 2924243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (mHours == null) { 2934243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson return String.format("%s:%s.%s",mMinutes, mSeconds, mHunderdths); 2944243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2954243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson return String.format("%s:%s:%s.%s",mHours, mMinutes, mSeconds, mHunderdths); 2964243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 2974243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 298932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting private static String getTimeStringForAccessibility(int hours, int minutes, int seconds, 299932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting boolean showNeg, Resources r) { 300932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting StringBuilder s = new StringBuilder(); 301932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting if (showNeg) { 302932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting // This must be followed by a non-zero number or it will be audible as "hyphen" 303932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting // instead of "minus". 304932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting s.append("-"); 305932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting } 306932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting if (showNeg && hours == 0 && minutes == 0) { 307932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting // Non-negative time will always have minutes, eg. "0 minutes 7 seconds", but negative 308932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting // time must start with non-zero digit, eg. -0m7s will be audible as just "-7 seconds" 309932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting s.append(String.format( 310932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting r.getQuantityText(R.plurals.Nseconds_description, seconds).toString(), 311932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting seconds)); 312932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting } else if (hours == 0) { 313932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting s.append(String.format( 314932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting r.getQuantityText(R.plurals.Nminutes_description, minutes).toString(), 315932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting minutes)); 316932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting s.append(" "); 317932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting s.append(String.format( 318932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting r.getQuantityText(R.plurals.Nseconds_description, seconds).toString(), 319932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting seconds)); 320932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting } else { 321932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting s.append(String.format( 322932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting r.getQuantityText(R.plurals.Nhours_description, hours).toString(), 323932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting hours)); 324932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting s.append(" "); 325932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting s.append(String.format( 326932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting r.getQuantityText(R.plurals.Nminutes_description, minutes).toString(), 327932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting minutes)); 328932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting s.append(" "); 329932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting s.append(String.format( 330932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting r.getQuantityText(R.plurals.Nseconds_description, seconds).toString(), 331932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting seconds)); 332932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting } 333932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting return s.toString(); 334932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting } 335932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting 336e40b31200dee36341e5697b2774799555ca79c9bSara Ting public void setVirtualButtonEnabled(boolean enabled) { 337e40b31200dee36341e5697b2774799555ca79c9bSara Ting mVirtualButtonEnabled = enabled; 338e40b31200dee36341e5697b2774799555ca79c9bSara Ting } 339e40b31200dee36341e5697b2774799555ca79c9bSara Ting 340e40b31200dee36341e5697b2774799555ca79c9bSara Ting private void virtualButtonPressed(boolean pressedOn) { 341e40b31200dee36341e5697b2774799555ca79c9bSara Ting mVirtualButtonPressedOn = pressedOn; 342386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein mStopStartTextView.setTextColor(pressedOn ? mPressedColor : mWhiteColor); 343e40b31200dee36341e5697b2774799555ca79c9bSara Ting invalidate(); 344e40b31200dee36341e5697b2774799555ca79c9bSara Ting } 345e40b31200dee36341e5697b2774799555ca79c9bSara Ting 346e40b31200dee36341e5697b2774799555ca79c9bSara Ting private boolean withinVirtualButtonBounds(float x, float y) { 347e40b31200dee36341e5697b2774799555ca79c9bSara Ting int width = getWidth(); 348e40b31200dee36341e5697b2774799555ca79c9bSara Ting int height = getHeight(); 349e40b31200dee36341e5697b2774799555ca79c9bSara Ting float centerX = width / 2; 350e40b31200dee36341e5697b2774799555ca79c9bSara Ting float centerY = height / 2; 351e40b31200dee36341e5697b2774799555ca79c9bSara Ting float radius = Math.min(width, height) / 2; 352e40b31200dee36341e5697b2774799555ca79c9bSara Ting 353e40b31200dee36341e5697b2774799555ca79c9bSara Ting // Within the circle button if distance to the center is less than the radius. 354e40b31200dee36341e5697b2774799555ca79c9bSara Ting double distance = Math.sqrt(Math.pow(centerX - x, 2) + Math.pow(centerY - y, 2)); 355e40b31200dee36341e5697b2774799555ca79c9bSara Ting return distance < radius; 356e40b31200dee36341e5697b2774799555ca79c9bSara Ting } 357e40b31200dee36341e5697b2774799555ca79c9bSara Ting 358e40b31200dee36341e5697b2774799555ca79c9bSara Ting public void registerVirtualButtonAction(final Runnable runnable) { 359932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting if (!mAccessibilityManager.isEnabled()) { 360932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting this.setOnTouchListener(new OnTouchListener() { 361932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting @Override 362932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting public boolean onTouch(View v, MotionEvent event) { 363932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting if (mVirtualButtonEnabled) { 364932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting switch (event.getAction()) { 365932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting case MotionEvent.ACTION_DOWN: 366932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting if (withinVirtualButtonBounds(event.getX(), event.getY())) { 367932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting virtualButtonPressed(true); 368932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting return true; 369932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting } else { 370932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting virtualButtonPressed(false); 371932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting return false; 372357497c341662c56945e22e458852f52a977efdfSam Blitzstein } 373932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting case MotionEvent.ACTION_CANCEL: 374932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting virtualButtonPressed(false); 375e40b31200dee36341e5697b2774799555ca79c9bSara Ting return true; 376932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting case MotionEvent.ACTION_OUTSIDE: 377e40b31200dee36341e5697b2774799555ca79c9bSara Ting virtualButtonPressed(false); 378e40b31200dee36341e5697b2774799555ca79c9bSara Ting return false; 379932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting case MotionEvent.ACTION_UP: 380932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting virtualButtonPressed(false); 381932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting if (withinVirtualButtonBounds(event.getX(), event.getY())) { 382932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting runnable.run(); 383357497c341662c56945e22e458852f52a977efdfSam Blitzstein } 384932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting return true; 385932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting } 386e40b31200dee36341e5697b2774799555ca79c9bSara Ting } 387932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting return false; 388e40b31200dee36341e5697b2774799555ca79c9bSara Ting } 389932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting }); 390932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting } else { 391932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting this.setOnClickListener(new OnClickListener() { 392932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting @Override 393932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting public void onClick(View v) { 394932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting runnable.run(); 395932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting } 396932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting }); 397932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting } 398e40b31200dee36341e5697b2774799555ca79c9bSara Ting } 399e40b31200dee36341e5697b2774799555ca79c9bSara Ting 4004243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson @Override 4014243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson public void onDraw(Canvas canvas) { 402e40b31200dee36341e5697b2774799555ca79c9bSara Ting // Blink functionality. 403e40b31200dee36341e5697b2774799555ca79c9bSara Ting if (!mShowTimeStr && !mVirtualButtonPressedOn) { 404e40b31200dee36341e5697b2774799555ca79c9bSara Ting return; 405e40b31200dee36341e5697b2774799555ca79c9bSara Ting } 406e40b31200dee36341e5697b2774799555ca79c9bSara Ting 4074243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson int width = getWidth(); 4084243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (mRemeasureText && width != 0) { 4094243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson setTotalTextWidth(); 410c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee width = getWidth(); 4114243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson mRemeasureText = false; 4124243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 4134243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 4144243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson int xCenter = width / 2; 4154243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson int yCenter = getHeight() / 2; 4164243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson 4174243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson float textXstart = xCenter - mTotalTextWidth / 2; 418c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee float textYstart = yCenter + mTextHeight/2 - (mTextHeight * FONT_VERTICAL_OFFSET); 419c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee // align the labels vertically to the top of the rest of the text 420c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee float labelYStart = textYstart - (mTextHeight * (1 - 2 * FONT_VERTICAL_OFFSET)) 421c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee + (1 - 2 * FONT_VERTICAL_OFFSET) * mPaintLabel.getTextSize(); 422e40b31200dee36341e5697b2774799555ca79c9bSara Ting 423e40b31200dee36341e5697b2774799555ca79c9bSara Ting // Text color differs based on pressed state. 424e40b31200dee36341e5697b2774799555ca79c9bSara Ting int textColor; 425e40b31200dee36341e5697b2774799555ca79c9bSara Ting if (mVirtualButtonPressedOn) { 426e40b31200dee36341e5697b2774799555ca79c9bSara Ting textColor = mPressedColor; 427386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein mStopStartTextView.setTextColor(mPressedColor); 428e40b31200dee36341e5697b2774799555ca79c9bSara Ting } else { 429e40b31200dee36341e5697b2774799555ca79c9bSara Ting textColor = mDefaultColor; 430e40b31200dee36341e5697b2774799555ca79c9bSara Ting } 431e40b31200dee36341e5697b2774799555ca79c9bSara Ting mPaintBig.setColor(textColor); 432e40b31200dee36341e5697b2774799555ca79c9bSara Ting mPaintBigThin.setColor(textColor); 433e40b31200dee36341e5697b2774799555ca79c9bSara Ting mPaintLabel.setColor(textColor); 434e40b31200dee36341e5697b2774799555ca79c9bSara Ting mPaintMed.setColor(textColor); 435e40b31200dee36341e5697b2774799555ca79c9bSara Ting 4364243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (mHours != null) { 4374243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson canvas.drawText(mHours, textXstart, textYstart, mPaintBig); 4384243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson textXstart += mHoursWidth; 439c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee canvas.drawText(mHoursLabel, textXstart, labelYStart, mPaintLabel); 4404243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson textXstart += mHoursLabelWidth; 4414243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 4424243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (mMinutes != null) { 4434243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson canvas.drawText(mMinutes, textXstart, textYstart, mPaintBig); 4444243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson textXstart += mMinutesWidth; 445c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee canvas.drawText(mMinutesLabel, textXstart, labelYStart, mPaintLabel); 4464243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson textXstart += mMinutesLabelWidth; 4474243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 4484243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (mSeconds != null) { 4494243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson canvas.drawText(mSeconds, textXstart, textYstart, mPaintBigThin); 4504243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson textXstart += mSecondsWidth; 451c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee canvas.drawText(mSecondsLabel, textXstart, labelYStart, mPaintLabel); 4524243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson textXstart += mSecondsLabelWidth; 4534243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 4544243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson if (mHunderdths != null) { 4554243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson canvas.drawText(HUNDREDTH_SEPERATOR, textXstart, textYstart, mPaintLabel); 4564243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson textXstart += mHundredthsSepWidth; 4574243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson canvas.drawText(mHunderdths, textXstart, textYstart, mPaintMed); 4584243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 459386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein } 460c78b68bfacfb9542e80ae2d37ed66ff27917578fYorke Lee 461386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein public void registerStopTextView(TextView stopStartTextView) { 462386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein mStopStartTextView = stopStartTextView; 4634243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson } 4644243fb005ecf4810eb2a1adc28df73abf431f178Isaac Katzenelson} 465