TimePickerSpinnerDelegate.java revision 67945c11a5e9547f71be91ceb99e7b9ff15a6292
1eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio/* 2eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Copyright (C) 2013 The Android Open Source Project 3eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 4eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License"); 5eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * you may not use this file except in compliance with the License. 6eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * You may obtain a copy of the License at 7eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 8eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * http://www.apache.org/licenses/LICENSE-2.0 9eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 10eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Unless required by applicable law or agreed to in writing, software 11eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS, 12eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * See the License for the specific language governing permissions and 14eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * limitations under the License. 15eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 16eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 17eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Megliopackage android.widget; 18eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 19eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.content.Context; 2060727e07c6ef72e2f494266939c02494a3df28f8Alan Viveretteimport android.content.res.ColorStateList; 21eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.content.res.Configuration; 22eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.content.res.Resources; 23eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.content.res.TypedArray; 24eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.os.Parcel; 25eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.os.Parcelable; 26eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.text.TextUtils; 27eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.text.format.DateFormat; 28014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglioimport android.text.format.DateUtils; 29eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.util.AttributeSet; 30eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.util.Log; 3167945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viveretteimport android.util.TypedValue; 32eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.HapticFeedbackConstants; 33eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.KeyCharacterMap; 34eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.KeyEvent; 35eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.LayoutInflater; 36eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.View; 37eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.ViewGroup; 38eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.accessibility.AccessibilityEvent; 39eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport android.view.accessibility.AccessibilityNodeInfo; 40eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 41eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport com.android.internal.R; 42eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 43eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport java.util.ArrayList; 44eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglioimport java.util.Calendar; 45014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglioimport java.util.Locale; 46eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 47eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio/** 4867945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette * A delegate implementing the radial clock-based TimePicker. 49eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 503053b2fdcf7486f2e2f572f9b05ce65dacdd2b4cChet Haaseclass TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate implements 51eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio RadialTimePickerView.OnValueSelectedListener { 52eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 53eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final String TAG = "TimePickerDelegate"; 54eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 55eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Index used by RadialPickerLayout 56eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int HOUR_INDEX = 0; 57eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int MINUTE_INDEX = 1; 58eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 59eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // NOT a real index for the purpose of what's showing. 60eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int AMPM_INDEX = 2; 61eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 62eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Also NOT a real index, just used for keyboard mode. 63eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int ENABLE_PICKER_INDEX = 3; 64eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 6567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette static final int AM = 0; 6667945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette static final int PM = 1; 67eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 68eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final boolean DEFAULT_ENABLED_STATE = true; 69eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean mIsEnabled = DEFAULT_ENABLED_STATE; 70eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 71eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static final int HOURS_IN_HALF_DAY = 12; 72eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 7367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final View mHeaderView; 7467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final TextView mHourView; 7567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final TextView mMinuteView; 7667945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final View mAmPmLayout; 7767945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final CheckedTextView mAmLabel; 7867945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final CheckedTextView mPmLabel; 7967945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final RadialTimePickerView mRadialTimePickerView; 8067945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final TextView mSeparatorView; 81eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 8267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final String mAmText; 8367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final String mPmText; 8467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 8567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final float mDisabledAlpha; 86eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 87eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean mAllowAutoAdvance; 88eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mInitialHourOfDay; 89eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mInitialMinute; 90eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean mIs24HourView; 91eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 92eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // For hardware IME input. 93eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private char mPlaceholderText; 94eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private String mDoublePlaceholderText; 95eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private String mDeletedKeyFormat; 96eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean mInKbMode; 97eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private ArrayList<Integer> mTypedTimes = new ArrayList<Integer>(); 98eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private Node mLegalTimesTree; 99eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mAmKeyCode; 100eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int mPmKeyCode; 101eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 102eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Accessibility strings. 103eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private String mHourPickerDescription; 104eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private String mSelectHours; 105eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private String mMinutePickerDescription; 106eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private String mSelectMinutes; 107eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 108014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio private Calendar mTempCalendar; 109014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio 1103053b2fdcf7486f2e2f572f9b05ce65dacdd2b4cChet Haase public TimePickerSpinnerDelegate(TimePicker delegator, Context context, AttributeSet attrs, 1113053b2fdcf7486f2e2f572f9b05ce65dacdd2b4cChet Haase int defStyleAttr, int defStyleRes) { 112eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio super(delegator, context); 113eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 114eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // process style attributes 115eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final TypedArray a = mContext.obtainStyledAttributes(attrs, 116eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio R.styleable.TimePicker, defStyleAttr, defStyleRes); 11760727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 11860727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette Context.LAYOUT_INFLATER_SERVICE); 119eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final Resources res = mContext.getResources(); 120eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 121eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHourPickerDescription = res.getString(R.string.hour_picker_description); 122eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectHours = res.getString(R.string.select_hours); 123eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMinutePickerDescription = res.getString(R.string.minute_picker_description); 124eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSelectMinutes = res.getString(R.string.select_minutes); 1251cc51a6c6c656c6ef0a0e57f2acd6f6d82f17bd9Elliott Hughes 1261cc51a6c6c656c6ef0a0e57f2acd6f6d82f17bd9Elliott Hughes String[] amPmStrings = TimePickerClockDelegate.getAmPmStrings(context); 1271cc51a6c6c656c6ef0a0e57f2acd6f6d82f17bd9Elliott Hughes mAmText = amPmStrings[0]; 1281cc51a6c6c656c6ef0a0e57f2acd6f6d82f17bd9Elliott Hughes mPmText = amPmStrings[1]; 129eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 13060727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout, 13160727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette R.layout.time_picker_holo); 13267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette final View mainView = inflater.inflate(layoutResourceId, delegator); 133eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 13467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mHeaderView = mainView.findViewById(R.id.time_header); 13567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground)); 13667945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 13767945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette // Set up hour/minute labels. 13867945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mHourView = (TextView) mHeaderView.findViewById(R.id.hours); 13967945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mHourView.setOnClickListener(mClickListener); 14067945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mSeparatorView = (TextView) mHeaderView.findViewById(R.id.separator); 14167945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mMinuteView = (TextView) mHeaderView.findViewById(R.id.minutes); 14267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mMinuteView.setOnClickListener(mClickListener); 1435134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette 14460727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette final int headerTimeTextAppearance = a.getResourceId( 14560727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette R.styleable.TimePicker_headerTimeTextAppearance, 0); 1465134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette if (headerTimeTextAppearance != 0) { 1475134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette mHourView.setTextAppearance(context, headerTimeTextAppearance); 1485134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette mSeparatorView.setTextAppearance(context, headerTimeTextAppearance); 1495134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette mMinuteView.setTextAppearance(context, headerTimeTextAppearance); 1505134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette } 1515134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette 15267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette // TODO: This can be removed once we support themed color state lists. 15360727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette final int headerSelectedTextColor = a.getColor( 15460727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette R.styleable.TimePicker_headerSelectedTextColor, 15560727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette res.getColor(R.color.timepicker_default_selector_color_material)); 15660727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette mHourView.setTextColor(ColorStateList.addFirstIfMissing(mHourView.getTextColors(), 15760727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette R.attr.state_selected, headerSelectedTextColor)); 15860727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette mMinuteView.setTextColor(ColorStateList.addFirstIfMissing(mMinuteView.getTextColors(), 15960727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette R.attr.state_selected, headerSelectedTextColor)); 16060727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette 16167945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette // Set up AM/PM labels. 16267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmPmLayout = mHeaderView.findViewById(R.id.ampm_layout); 16367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.am_label); 16467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmLabel.setText(amPmStrings[0]); 16567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmLabel.setOnClickListener(mClickListener); 16667945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mPmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.pm_label); 16767945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mPmLabel.setText(amPmStrings[1]); 16867945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mPmLabel.setOnClickListener(mClickListener); 16967945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 17060727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette final int headerAmPmTextAppearance = a.getResourceId( 17160727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette R.styleable.TimePicker_headerAmPmTextAppearance, 0); 1725134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette if (headerAmPmTextAppearance != 0) { 17367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmLabel.setTextAppearance(context, headerAmPmTextAppearance); 17467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mPmLabel.setTextAppearance(context, headerAmPmTextAppearance); 1755134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette } 1765134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette 17760727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette a.recycle(); 1785134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette 17967945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette // Pull disabled alpha from theme. 18067945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette final TypedValue outValue = new TypedValue(); 18167945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true); 18267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mDisabledAlpha = outValue.getFloat(); 18367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 18460727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById( 18560727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette R.id.radial_picker); 186eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 187eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setupListeners(); 188eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 189eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAllowAutoAdvance = true; 190eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 191eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Set up for keyboard mode. 192eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mDoublePlaceholderText = res.getString(R.string.time_placeholder); 193eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mDeletedKeyFormat = res.getString(R.string.deleted_key); 194eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPlaceholderText = mDoublePlaceholderText.charAt(0); 195eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmKeyCode = mPmKeyCode = -1; 196eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio generateLegalTimesTree(); 197eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 198eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Initialize with current time 199eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final Calendar calendar = Calendar.getInstance(mCurrentLocale); 200eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int currentHour = calendar.get(Calendar.HOUR_OF_DAY); 201eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int currentMinute = calendar.get(Calendar.MINUTE); 202518ff0de95e64116ecb07706fc564d4c19197ca7Alan Viverette initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX); 203eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 204eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 205518ff0de95e64116ecb07706fc564d4c19197ca7Alan Viverette private void initialize(int hourOfDay, int minute, boolean is24HourView, int index) { 206eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInitialHourOfDay = hourOfDay; 207eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInitialMinute = minute; 208eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIs24HourView = is24HourView; 209eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInKbMode = false; 210eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateUI(index); 211eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 212eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 213eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void setupListeners() { 214ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette mHeaderView.setOnKeyListener(mKeyListener); 215ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette mHeaderView.setOnFocusChangeListener(mFocusListener); 216ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette mHeaderView.setFocusable(true); 217eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 218eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setOnValueSelectedListener(this); 219eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 220eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 221eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void updateUI(int index) { 222eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Update RadialPicker values 223eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateRadialPicker(index); 224eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Enable or disable the AM/PM view. 225eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderAmPm(); 226eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Update Hour and Minutes 227eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderHour(mInitialHourOfDay, true); 228eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Update time separator 229eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderSeparator(); 230eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Update Minutes 231eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderMinute(mInitialMinute); 232eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Invalidate everything 233eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mDelegator.invalidate(); 234eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 235eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 236eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void updateRadialPicker(int index) { 237eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.initialize(mInitialHourOfDay, mInitialMinute, mIs24HourView); 2387119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette setCurrentItemShowing(index, false, true); 239eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 240eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 241eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int computeMaxWidthOfNumbers(int max) { 242eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio TextView tempView = new TextView(mContext); 2435134478151d8aa3d776f8d4f368dbcdbc501a92aAlan Viverette tempView.setTextAppearance(mContext, R.style.TextAppearance_Material_TimePicker_TimeLabel); 244eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 245eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio ViewGroup.LayoutParams.WRAP_CONTENT); 246eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio tempView.setLayoutParams(lp); 247eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int maxWidth = 0; 248eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (int minutes = 0; minutes < max; minutes++) { 249eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final String text = String.format("%02d", minutes); 250eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio tempView.setText(text); 251eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio tempView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); 252eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio maxWidth = Math.max(maxWidth, tempView.getMeasuredWidth()); 253eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 254eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return maxWidth; 255eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 256eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 257eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void updateHeaderAmPm() { 258eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourView) { 25967945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmPmLayout.setVisibility(View.GONE); 260eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 26167945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette final String bestDateTimePattern = DateFormat.getBestDateTimePattern( 26267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mCurrentLocale, "hm"); 263eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio boolean amPmOnLeft = bestDateTimePattern.startsWith("a"); 264eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (TextUtils.getLayoutDirectionFromLocale(mCurrentLocale) == 265eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio View.LAYOUT_DIRECTION_RTL) { 266eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio amPmOnLeft = !amPmOnLeft; 267eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 268eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 26967945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette final ViewGroup.MarginLayoutParams params = 27067945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette (ViewGroup.MarginLayoutParams) mAmPmLayout.getLayoutParams(); 271eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 272eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (amPmOnLeft) { 27367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette params.leftMargin = 0; 27467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette params.rightMargin = computeMaxWidthOfNumbers(12 /* for hours */); 275eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 27667945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette params.leftMargin = computeMaxWidthOfNumbers(60 /* for minutes */); 27767945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette params.rightMargin = 0; 278eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 279eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 28067945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmPmLayout.setLayoutParams(params); 28167945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmPmLayout.setVisibility(View.VISIBLE); 28267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 28367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM); 284eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 285eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 286eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 287eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 288eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Set the current hour. 289eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 290eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 291eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setCurrentHour(Integer currentHour) { 292eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mInitialHourOfDay == currentHour) { 293eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return; 294eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 295eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInitialHourOfDay = currentHour; 296eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderHour(currentHour, true /* accessibility announce */); 297eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderAmPm(); 298eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setCurrentHour(currentHour); 299eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setAmOrPm(mInitialHourOfDay < 12 ? AM : PM); 300eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mDelegator.invalidate(); 301eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio onTimeChanged(); 302eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 303eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 304eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 305eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @return The current hour in the range (0-23). 306eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 307eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 308eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public Integer getCurrentHour() { 309eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int currentHour = mRadialTimePickerView.getCurrentHour(); 310eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourView) { 311eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return currentHour; 312eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 313eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio switch(mRadialTimePickerView.getAmOrPm()) { 314eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case PM: 315eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY; 316eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case AM: 317eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio default: 318eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return currentHour % HOURS_IN_HALF_DAY; 319eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 320eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 321eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 322eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 323eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 324eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Set the current minute (0-59). 325eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 326eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 327eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setCurrentMinute(Integer currentMinute) { 328eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mInitialMinute == currentMinute) { 329eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return; 330eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 331eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInitialMinute = currentMinute; 332eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderMinute(currentMinute); 333eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setCurrentMinute(currentMinute); 334eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mDelegator.invalidate(); 335eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio onTimeChanged(); 336eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 337eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 338eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 339eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @return The current minute. 340eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 341eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 342eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public Integer getCurrentMinute() { 343eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mRadialTimePickerView.getCurrentMinute(); 344eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 345eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 346eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 347eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Set whether in 24 hour or AM/PM mode. 348eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 349eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @param is24HourView True = 24 hour mode. False = AM/PM. 350eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 351eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 352eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setIs24HourView(Boolean is24HourView) { 353eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (is24HourView == mIs24HourView) { 354eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return; 355eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 356eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIs24HourView = is24HourView; 357eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio generateLegalTimesTree(); 358eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int hour = mRadialTimePickerView.getCurrentHour(); 359eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInitialHourOfDay = hour; 360eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderHour(hour, false /* no accessibility announce */); 361eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderAmPm(); 362eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateRadialPicker(mRadialTimePickerView.getCurrentItemShowing()); 363eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mDelegator.invalidate(); 364eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 365eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 366eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 367eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @return true if this is in 24 hour view else false. 368eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 369eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 370eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean is24HourView() { 371eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mIs24HourView; 372eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 373eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 374eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 375eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener callback) { 376eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mOnTimeChangedListener = callback; 377eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 378eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 379eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 380eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void setEnabled(boolean enabled) { 381eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHourView.setEnabled(enabled); 382eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMinuteView.setEnabled(enabled); 38367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmLabel.setEnabled(enabled); 38467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mPmLabel.setEnabled(enabled); 385eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setEnabled(enabled); 386eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIsEnabled = enabled; 387eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 388eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 389eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 390eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean isEnabled() { 391eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mIsEnabled; 392eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 393eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 394eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 395eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public int getBaseline() { 396eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // does not support baseline alignment 397eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return -1; 398eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 399eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 400eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 401eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onConfigurationChanged(Configuration newConfig) { 402eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateUI(mRadialTimePickerView.getCurrentItemShowing()); 403eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 404eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 405eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 406eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public Parcelable onSaveInstanceState(Parcelable superState) { 407eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return new SavedState(superState, getCurrentHour(), getCurrentMinute(), 408518ff0de95e64116ecb07706fc564d4c19197ca7Alan Viverette is24HourView(), inKbMode(), getTypedTimes(), getCurrentItemShowing()); 409eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 410eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 411eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 412eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onRestoreInstanceState(Parcelable state) { 413eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio SavedState ss = (SavedState) state; 414eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setInKbMode(ss.inKbMode()); 415eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio setTypedTimes(ss.getTypesTimes()); 416518ff0de95e64116ecb07706fc564d4c19197ca7Alan Viverette initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing()); 417eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.invalidate(); 418eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mInKbMode) { 419eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio tryStartingKbMode(-1); 420eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHourView.invalidate(); 421eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 422eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 423eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 424eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 425014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio public void setCurrentLocale(Locale locale) { 426014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio super.setCurrentLocale(locale); 427014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio mTempCalendar = Calendar.getInstance(locale); 428014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio } 429014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio 430014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio @Override 431eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 432014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio onPopulateAccessibilityEvent(event); 433014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio return true; 434eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 435eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 436eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 437eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 438014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio int flags = DateUtils.FORMAT_SHOW_TIME; 439014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio if (mIs24HourView) { 440014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio flags |= DateUtils.FORMAT_24HOUR; 441014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio } else { 442014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio flags |= DateUtils.FORMAT_12HOUR; 443014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio } 444014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio mTempCalendar.set(Calendar.HOUR_OF_DAY, getCurrentHour()); 445014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio mTempCalendar.set(Calendar.MINUTE, getCurrentMinute()); 446014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio String selectedDate = DateUtils.formatDateTime(mContext, 447014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio mTempCalendar.getTimeInMillis(), flags); 448014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio event.getText().add(selectedDate); 449eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 450eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 451eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 452eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 453014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio event.setClassName(TimePicker.class.getName()); 454eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 455eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 456eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 457eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 458014b8cfcf87507e629a728582b196b62aee71e37Fabrice Di Meglio info.setClassName(TimePicker.class.getName()); 459eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 460eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 461eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 462eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Set whether in keyboard mode or not. 463eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 464eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @param inKbMode True means in keyboard mode. 465eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 466eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void setInKbMode(boolean inKbMode) { 467eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInKbMode = inKbMode; 468eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 469eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 470eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 471eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @return true if in keyboard mode 472eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 473eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean inKbMode() { 474eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mInKbMode; 475eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 476eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 477eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void setTypedTimes(ArrayList<Integer> typeTimes) { 478eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypedTimes = typeTimes; 479eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 480eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 481eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 482eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @return an array of typed times 483eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 484eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private ArrayList<Integer> getTypedTimes() { 485eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mTypedTimes; 486eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 487eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 488eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 489eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @return the index of the current item showing 490eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 491eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int getCurrentItemShowing() { 492eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mRadialTimePickerView.getCurrentItemShowing(); 493eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 494eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 495eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 496eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Propagate the time change 497eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 498eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void onTimeChanged() { 499eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 500eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mOnTimeChangedListener != null) { 501eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mOnTimeChangedListener.onTimeChanged(mDelegator, 502eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio getCurrentHour(), getCurrentMinute()); 503eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 504eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 505eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 506eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 507eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Used to save / restore state of time picker 508eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 509eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static class SavedState extends View.BaseSavedState { 510eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 511eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final int mHour; 512eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final int mMinute; 513eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final boolean mIs24HourMode; 514eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final boolean mInKbMode; 515eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final ArrayList<Integer> mTypedTimes; 516eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private final int mCurrentItemShowing; 517eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 518eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode, 519eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio boolean isKbMode, ArrayList<Integer> typedTimes, 520518ff0de95e64116ecb07706fc564d4c19197ca7Alan Viverette int currentItemShowing) { 521eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio super(superState); 522eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHour = hour; 523eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMinute = minute; 524eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIs24HourMode = is24HourMode; 525eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInKbMode = isKbMode; 526eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypedTimes = typedTimes; 527eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mCurrentItemShowing = currentItemShowing; 528eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 529eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 530eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private SavedState(Parcel in) { 531eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio super(in); 532eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHour = in.readInt(); 533eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMinute = in.readInt(); 534eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mIs24HourMode = (in.readInt() == 1); 535eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInKbMode = (in.readInt() == 1); 536eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypedTimes = in.readArrayList(getClass().getClassLoader()); 537eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mCurrentItemShowing = in.readInt(); 538eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 539eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 540eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public int getHour() { 541eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mHour; 542eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 543eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 544eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public int getMinute() { 545eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mMinute; 546eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 547eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 548eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean is24HourMode() { 549eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mIs24HourMode; 550eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 551eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 552eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean inKbMode() { 553eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mInKbMode; 554eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 555eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 556eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public ArrayList<Integer> getTypesTimes() { 557eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mTypedTimes; 558eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 559eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 560eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public int getCurrentItemShowing() { 561eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mCurrentItemShowing; 562eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 563eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 564eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 565eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void writeToParcel(Parcel dest, int flags) { 566eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio super.writeToParcel(dest, flags); 567eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio dest.writeInt(mHour); 568eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio dest.writeInt(mMinute); 569eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio dest.writeInt(mIs24HourMode ? 1 : 0); 570eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio dest.writeInt(mInKbMode ? 1 : 0); 571eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio dest.writeList(mTypedTimes); 572eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio dest.writeInt(mCurrentItemShowing); 573eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 574eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 575eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @SuppressWarnings({"unused", "hiding"}) 576eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() { 577eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public SavedState createFromParcel(Parcel in) { 578eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return new SavedState(in); 579eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 580eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 581eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public SavedState[] newArray(int size) { 582eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return new SavedState[size]; 583eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 584eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio }; 585eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 586eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 587eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void tryVibrate() { 588eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mDelegator.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); 589eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 590eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 59167945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private void updateAmPmLabelStates(int amOrPm) { 59267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette final boolean isAm = amOrPm == AM; 59367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmLabel.setChecked(isAm); 59467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mAmLabel.setAlpha(isAm ? 1 : mDisabledAlpha); 59567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 59667945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette final boolean isPm = amOrPm == PM; 59767945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mPmLabel.setChecked(isPm); 59867945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mPmLabel.setAlpha(isPm ? 1 : mDisabledAlpha); 599eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 600eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 601eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 602eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Called by the picker for updating the header display. 603eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 604eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 605eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) { 606eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (pickerIndex == HOUR_INDEX) { 607eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderHour(newValue, false); 608eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String announcement = String.format("%d", newValue); 609eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mAllowAutoAdvance && autoAdvance) { 6107119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette setCurrentItemShowing(MINUTE_INDEX, true, false); 611eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio announcement += ". " + mSelectMinutes; 612eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 613eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setContentDescription( 614eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHourPickerDescription + ": " + newValue); 615eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 616eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 617eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.announceForAccessibility(announcement); 618eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (pickerIndex == MINUTE_INDEX){ 619eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderMinute(newValue); 620eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + newValue); 621eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (pickerIndex == AMPM_INDEX) { 62267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette updateAmPmLabelStates(newValue); 623eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (pickerIndex == ENABLE_PICKER_INDEX) { 624eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!isTypedTimeFullyLegal()) { 625eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypedTimes.clear(); 626eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 627ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette finishKbMode(); 628eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 629eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 630eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 631eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void updateHeaderHour(int value, boolean announce) { 632eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, 633eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio (mIs24HourView) ? "Hm" : "hm"); 634eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int lengthPattern = bestDateTimePattern.length(); 635eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio boolean hourWithTwoDigit = false; 636eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio char hourFormat = '\0'; 637eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save 638eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // the hour format that we found. 639eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (int i = 0; i < lengthPattern; i++) { 640eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final char c = bestDateTimePattern.charAt(i); 641eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (c == 'H' || c == 'h' || c == 'K' || c == 'k') { 642eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio hourFormat = c; 643eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) { 644eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio hourWithTwoDigit = true; 645eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 646eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio break; 647eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 648eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 649eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final String format; 650eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (hourWithTwoDigit) { 651eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio format = "%02d"; 652eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 653eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio format = "%d"; 654eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 655eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourView) { 656eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // 'k' means 1-24 hour 657eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (hourFormat == 'k' && value == 0) { 658eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio value = 24; 659eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 660eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 661eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // 'K' means 0-11 hour 662eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio value = modulo12(value, hourFormat == 'K'); 663eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 664eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio CharSequence text = String.format(format, value); 665eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHourView.setText(text); 666eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (announce) { 667eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.announceForAccessibility(text); 668eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 669eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 670eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 671eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private static int modulo12(int n, boolean startWithZero) { 672eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int value = n % 12; 673eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (value == 0 && !startWithZero) { 674eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio value = 12; 675eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 676eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return value; 677eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 678eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 679eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 680eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":". 681eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 682eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * See http://unicode.org/cldr/trac/browser/trunk/common/main 683eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 684eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the 685eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * separator as the character which is just after the hour marker in the returned pattern. 686eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 687eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void updateHeaderSeparator() { 688eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, 689eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio (mIs24HourView) ? "Hm" : "hm"); 690eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final String separatorText; 691eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // See http://www.unicode.org/reports/tr35/tr35-dates.html for hour formats 692eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final char[] hourFormats = {'H', 'h', 'K', 'k'}; 693eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int hIndex = lastIndexOfAny(bestDateTimePattern, hourFormats); 694eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (hIndex == -1) { 695eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Default case 696eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio separatorText = ":"; 697eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 698eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1)); 699eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 700eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mSeparatorView.setText(separatorText); 701eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 702eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 703eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio static private int lastIndexOfAny(String str, char[] any) { 704eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int lengthAny = any.length; 705eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (lengthAny > 0) { 706eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (int i = str.length() - 1; i >= 0; i--) { 707eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio char c = str.charAt(i); 708eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (int j = 0; j < lengthAny; j++) { 709eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (c == any[j]) { 710eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return i; 711eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 712eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 713eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 714eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 715eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return -1; 716eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 717eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 718eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void updateHeaderMinute(int value) { 719eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (value == 60) { 720eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio value = 0; 721eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 722eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio CharSequence text = String.format(mCurrentLocale, "%02d", value); 723eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.announceForAccessibility(text); 724eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMinuteView.setText(text); 725eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 726eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 727eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 728eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Show either Hours or Minutes. 729eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 7307119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette private void setCurrentItemShowing(int index, boolean animateCircle, boolean announce) { 731eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setCurrentItemShowing(index, animateCircle); 732eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 733eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (index == HOUR_INDEX) { 734eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int hours = mRadialTimePickerView.getCurrentHour(); 735eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mIs24HourView) { 736eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio hours = hours % 12; 737eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 738eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setContentDescription(mHourPickerDescription + ": " + hours); 739eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (announce) { 740eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.announceForAccessibility(mSelectHours); 741eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 742eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 743eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int minutes = mRadialTimePickerView.getCurrentMinute(); 744eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + minutes); 745eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (announce) { 746eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.announceForAccessibility(mSelectMinutes); 747eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 748eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 749eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 75060727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette mHourView.setSelected(index == HOUR_INDEX); 75160727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette mMinuteView.setSelected(index == MINUTE_INDEX); 752eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 753eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 75467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private void setAmOrPm(int amOrPm) { 75567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette updateAmPmLabelStates(amOrPm); 75667945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette mRadialTimePickerView.setAmOrPm(amOrPm); 75767945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette } 75867945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 759eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 760eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * For keyboard mode, processes key events. 761eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 762eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @param keyCode the pressed key. 763eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 764eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @return true if the key was successfully processed, false otherwise. 765eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 766eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean processKeyUp(int keyCode) { 767ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette if (keyCode == KeyEvent.KEYCODE_DEL) { 768eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mInKbMode) { 769eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mTypedTimes.isEmpty()) { 770eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int deleted = deleteLastTypedKey(); 771eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String deletedKeyStr; 772eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (deleted == getAmOrPmKeyCode(AM)) { 773eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio deletedKeyStr = mAmText; 774eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (deleted == getAmOrPmKeyCode(PM)) { 775eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio deletedKeyStr = mPmText; 776eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 777eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio deletedKeyStr = String.format("%d", getValFromKeyCode(deleted)); 778eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 779eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.announceForAccessibility( 780eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String.format(mDeletedKeyFormat, deletedKeyStr)); 781eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateDisplay(true); 782eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 783eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 784eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (keyCode == KeyEvent.KEYCODE_0 || keyCode == KeyEvent.KEYCODE_1 785eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio || keyCode == KeyEvent.KEYCODE_2 || keyCode == KeyEvent.KEYCODE_3 786eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio || keyCode == KeyEvent.KEYCODE_4 || keyCode == KeyEvent.KEYCODE_5 787eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio || keyCode == KeyEvent.KEYCODE_6 || keyCode == KeyEvent.KEYCODE_7 788eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio || keyCode == KeyEvent.KEYCODE_8 || keyCode == KeyEvent.KEYCODE_9 789eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio || (!mIs24HourView && 790eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio (keyCode == getAmOrPmKeyCode(AM) || keyCode == getAmOrPmKeyCode(PM)))) { 791eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mInKbMode) { 792eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mRadialTimePickerView == null) { 793eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Something's wrong, because time picker should definitely not be null. 794eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Log.e(TAG, "Unable to initiate keyboard mode, TimePicker was null."); 795eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return true; 796eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 797eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypedTimes.clear(); 798eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio tryStartingKbMode(keyCode); 799eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return true; 800eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 801eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We're already in keyboard mode. 802eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (addKeyIfLegal(keyCode)) { 803eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateDisplay(false); 804eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 805eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return true; 806eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 807eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return false; 808eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 809eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 810eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 811eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Try to start keyboard mode with the specified key. 812eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 813eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @param keyCode The key to use as the first press. Keyboard mode will not be started if the 814eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * key is not legal to start with. Or, pass in -1 to get into keyboard mode without a starting 815eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * key. 816eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 817eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void tryStartingKbMode(int keyCode) { 818eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (keyCode == -1 || addKeyIfLegal(keyCode)) { 819eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInKbMode = true; 820518ff0de95e64116ecb07706fc564d4c19197ca7Alan Viverette onValidationChanged(false); 821eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateDisplay(false); 822eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setInputEnabled(false); 823eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 824eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 825eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 826eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean addKeyIfLegal(int keyCode) { 827eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // If we're in 24hour mode, we'll need to check if the input is full. If in AM/PM mode, 828eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // we'll need to see if AM/PM have been typed. 829eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if ((mIs24HourView && mTypedTimes.size() == 4) || 830eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio (!mIs24HourView && isTypedTimeFullyLegal())) { 831eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return false; 832eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 833eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 834eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypedTimes.add(keyCode); 835eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!isTypedTimeLegalSoFar()) { 836eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio deleteLastTypedKey(); 837eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return false; 838eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 839eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 840eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int val = getValFromKeyCode(keyCode); 841eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.announceForAccessibility(String.format("%d", val)); 842eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Automatically fill in 0's if AM or PM was legally entered. 843eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (isTypedTimeFullyLegal()) { 844eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mIs24HourView && mTypedTimes.size() <= 3) { 845eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0); 846eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0); 847eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 848518ff0de95e64116ecb07706fc564d4c19197ca7Alan Viverette onValidationChanged(true); 849eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 850eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 851eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return true; 852eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 853eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 854eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 855eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Traverse the tree to see if the keys that have been typed so far are legal as is, 856eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * or may become legal as more keys are typed (excluding backspace). 857eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 858eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean isTypedTimeLegalSoFar() { 859eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node node = mLegalTimesTree; 860eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (int keyCode : mTypedTimes) { 861eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio node = node.canReach(keyCode); 862eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (node == null) { 863eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return false; 864eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 865eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 866eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return true; 867eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 868eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 869eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 870eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Check if the time that has been typed so far is completely legal, as is. 871eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 872eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private boolean isTypedTimeFullyLegal() { 873eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourView) { 874eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // For 24-hour mode, the time is legal if the hours and minutes are each legal. Note: 875eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // getEnteredTime() will ONLY call isTypedTimeFullyLegal() when NOT in 24hour mode. 876eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int[] values = getEnteredTime(null); 877eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return (values[0] >= 0 && values[1] >= 0 && values[1] < 60); 878eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 879eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // For AM/PM mode, the time is legal if it contains an AM or PM, as those can only be 880eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // legally added at specific times based on the tree's algorithm. 881eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return (mTypedTimes.contains(getAmOrPmKeyCode(AM)) || 882eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypedTimes.contains(getAmOrPmKeyCode(PM))); 883eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 884eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 885eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 886eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int deleteLastTypedKey() { 887eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int deleted = mTypedTimes.remove(mTypedTimes.size() - 1); 888eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!isTypedTimeFullyLegal()) { 889518ff0de95e64116ecb07706fc564d4c19197ca7Alan Viverette onValidationChanged(false); 890eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 891eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return deleted; 892eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 893eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 894eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 895eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time. 896eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 897ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette private void finishKbMode() { 898eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mInKbMode = false; 899eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mTypedTimes.isEmpty()) { 900eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int values[] = getEnteredTime(null); 901eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setCurrentHour(values[0]); 902eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setCurrentMinute(values[1]); 903eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mIs24HourView) { 904eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mRadialTimePickerView.setAmOrPm(values[2]); 905eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 906eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mTypedTimes.clear(); 907eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 908ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette updateDisplay(false); 909ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette mRadialTimePickerView.setInputEnabled(true); 910eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 911eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 912eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 913eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Update the hours, minutes, and AM/PM displays with the typed times. If the typedTimes is 914eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * empty, either show an empty display (filled with the placeholder text), or update from the 915eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * timepicker's values. 916eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 917eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @param allowEmptyDisplay if true, then if the typedTimes is empty, use the placeholder text. 918eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Otherwise, revert to the timepicker's values. 919eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 920eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void updateDisplay(boolean allowEmptyDisplay) { 921eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!allowEmptyDisplay && mTypedTimes.isEmpty()) { 922eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int hour = mRadialTimePickerView.getCurrentHour(); 923eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int minute = mRadialTimePickerView.getCurrentMinute(); 924eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderHour(hour, true); 925eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio updateHeaderMinute(minute); 926eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mIs24HourView) { 92767945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette updateAmPmLabelStates(hour < 12 ? AM : PM); 928eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 9297119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette setCurrentItemShowing(mRadialTimePickerView.getCurrentItemShowing(), true, true); 930518ff0de95e64116ecb07706fc564d4c19197ca7Alan Viverette onValidationChanged(true); 931eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 932eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio boolean[] enteredZeros = {false, false}; 933eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int[] values = getEnteredTime(enteredZeros); 934eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String hourFormat = enteredZeros[0] ? "%02d" : "%2d"; 935eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String minuteFormat = (enteredZeros[1]) ? "%02d" : "%2d"; 936eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String hourStr = (values[0] == -1) ? mDoublePlaceholderText : 937eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String.format(hourFormat, values[0]).replace(' ', mPlaceholderText); 938eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String minuteStr = (values[1] == -1) ? mDoublePlaceholderText : 939eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio String.format(minuteFormat, values[1]).replace(' ', mPlaceholderText); 940eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mHourView.setText(hourStr); 94160727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette mHourView.setSelected(false); 942eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mMinuteView.setText(minuteStr); 94360727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette mMinuteView.setSelected(false); 944eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mIs24HourView) { 94567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette updateAmPmLabelStates(values[2]); 946eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 947eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 948eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 949eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 950eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int getValFromKeyCode(int keyCode) { 951eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio switch (keyCode) { 952eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case KeyEvent.KEYCODE_0: 953eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return 0; 954eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case KeyEvent.KEYCODE_1: 955eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return 1; 956eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case KeyEvent.KEYCODE_2: 957eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return 2; 958eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case KeyEvent.KEYCODE_3: 959eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return 3; 960eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case KeyEvent.KEYCODE_4: 961eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return 4; 962eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case KeyEvent.KEYCODE_5: 963eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return 5; 964eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case KeyEvent.KEYCODE_6: 965eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return 6; 966eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case KeyEvent.KEYCODE_7: 967eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return 7; 968eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case KeyEvent.KEYCODE_8: 969eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return 8; 970eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio case KeyEvent.KEYCODE_9: 971eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return 9; 972eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio default: 973eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return -1; 974eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 975eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 976eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 977eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 978eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Get the currently-entered time, as integer values of the hours and minutes typed. 979eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 980eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @param enteredZeros A size-2 boolean array, which the caller should initialize, and which 981eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * may then be used for the caller to know whether zeros had been explicitly entered as either 982eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * hours of minutes. This is helpful for deciding whether to show the dashes, or actual 0's. 983eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * 984eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * @return A size-3 int array. The first value will be the hours, the second value will be the 985eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * minutes, and the third will be either AM or PM. 986eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 987eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int[] getEnteredTime(boolean[] enteredZeros) { 988eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int amOrPm = -1; 989eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int startIndex = 1; 990eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (!mIs24HourView && isTypedTimeFullyLegal()) { 991eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int keyCode = mTypedTimes.get(mTypedTimes.size() - 1); 992eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (keyCode == getAmOrPmKeyCode(AM)) { 993eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio amOrPm = AM; 994eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (keyCode == getAmOrPmKeyCode(PM)){ 995eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio amOrPm = PM; 996eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 997eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio startIndex = 2; 998eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 999eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int minute = -1; 1000eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int hour = -1; 1001eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (int i = startIndex; i <= mTypedTimes.size(); i++) { 1002eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio int val = getValFromKeyCode(mTypedTimes.get(mTypedTimes.size() - i)); 1003eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (i == startIndex) { 1004eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio minute = val; 1005eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (i == startIndex+1) { 1006eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio minute += 10 * val; 1007eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (enteredZeros != null && val == 0) { 1008eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio enteredZeros[1] = true; 1009eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1010eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (i == startIndex+2) { 1011eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio hour = val; 1012eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (i == startIndex+3) { 1013eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio hour += 10 * val; 1014eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (enteredZeros != null && val == 0) { 1015eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio enteredZeros[0] = true; 1016eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1017eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1018eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1019eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 102060727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette return new int[] { hour, minute, amOrPm }; 1021eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1022eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1023eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 1024eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Get the keycode value for AM and PM in the current language. 1025eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 1026eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int getAmOrPmKeyCode(int amOrPm) { 1027eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Cache the codes. 1028eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mAmKeyCode == -1 || mPmKeyCode == -1) { 1029eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Find the first character in the AM/PM text that is unique. 1030eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); 1031eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio char amChar; 1032eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio char pmChar; 1033eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (int i = 0; i < Math.max(mAmText.length(), mPmText.length()); i++) { 1034eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio amChar = mAmText.toLowerCase(mCurrentLocale).charAt(i); 1035eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio pmChar = mPmText.toLowerCase(mCurrentLocale).charAt(i); 1036eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (amChar != pmChar) { 1037eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio KeyEvent[] events = kcm.getEvents(new char[]{amChar, pmChar}); 1038eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // There should be 4 events: a down and up for both AM and PM. 1039eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (events != null && events.length == 4) { 1040eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mAmKeyCode = events[0].getKeyCode(); 1041eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mPmKeyCode = events[2].getKeyCode(); 1042eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1043eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Log.e(TAG, "Unable to find keycodes for AM and PM."); 1044eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1045eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio break; 1046eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1047eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1048eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1049eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (amOrPm == AM) { 1050eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mAmKeyCode; 1051eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else if (amOrPm == PM) { 1052eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return mPmKeyCode; 1053eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1054eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1055eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return -1; 1056eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1057eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1058eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 1059eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Create a tree for deciding what keys can legally be typed. 1060eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 1061eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private void generateLegalTimesTree() { 1062eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Create a quick cache of numbers to their keycodes. 1063eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int k0 = KeyEvent.KEYCODE_0; 1064eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int k1 = KeyEvent.KEYCODE_1; 1065eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int k2 = KeyEvent.KEYCODE_2; 1066eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int k3 = KeyEvent.KEYCODE_3; 1067eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int k4 = KeyEvent.KEYCODE_4; 1068eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int k5 = KeyEvent.KEYCODE_5; 1069eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int k6 = KeyEvent.KEYCODE_6; 1070eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int k7 = KeyEvent.KEYCODE_7; 1071eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int k8 = KeyEvent.KEYCODE_8; 1072eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio final int k9 = KeyEvent.KEYCODE_9; 1073eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1074eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The root of the tree doesn't contain any numbers. 1075eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mLegalTimesTree = new Node(); 1076eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mIs24HourView) { 1077eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We'll be re-using these nodes, so we'll save them. 1078eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node minuteFirstDigit = new Node(k0, k1, k2, k3, k4, k5); 1079eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node minuteSecondDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); 1080eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The first digit must be followed by the second digit. 1081eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio minuteFirstDigit.addChild(minuteSecondDigit); 1082eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1083eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The first digit may be 0-1. 1084eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node firstDigit = new Node(k0, k1); 1085eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mLegalTimesTree.addChild(firstDigit); 1086eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1087eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 0-1, the second digit may be 0-5. 1088eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node secondDigit = new Node(k0, k1, k2, k3, k4, k5); 1089eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit.addChild(secondDigit); 1090eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We may now be followed by the first minute digit. E.g. 00:09, 15:58. 1091eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit.addChild(minuteFirstDigit); 1092eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1093eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 0-1, and the second digit is 0-5, the third digit may be 6-9. 1094eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node thirdDigit = new Node(k6, k7, k8, k9); 1095eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The time must now be finished. E.g. 0:55, 1:08. 1096eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit.addChild(thirdDigit); 1097eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1098eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 0-1, the second digit may be 6-9. 1099eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit = new Node(k6, k7, k8, k9); 1100eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit.addChild(secondDigit); 1101eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We must now be followed by the first minute digit. E.g. 06:50, 18:20. 1102eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit.addChild(minuteFirstDigit); 1103eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1104eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The first digit may be 2. 1105eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit = new Node(k2); 1106eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mLegalTimesTree.addChild(firstDigit); 1107eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1108eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 2, the second digit may be 0-3. 1109eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit = new Node(k0, k1, k2, k3); 1110eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit.addChild(secondDigit); 1111eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We must now be followed by the first minute digit. E.g. 20:50, 23:09. 1112eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit.addChild(minuteFirstDigit); 1113eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1114eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 2, the second digit may be 4-5. 1115eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit = new Node(k4, k5); 1116eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit.addChild(secondDigit); 1117eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We must now be followd by the last minute digit. E.g. 2:40, 2:53. 1118eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit.addChild(minuteSecondDigit); 1119eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1120eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The first digit may be 3-9. 1121eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit = new Node(k3, k4, k5, k6, k7, k8, k9); 1122eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mLegalTimesTree.addChild(firstDigit); 1123eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We must now be followed by the first minute digit. E.g. 3:57, 8:12. 1124eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit.addChild(minuteFirstDigit); 1125eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } else { 1126eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We'll need to use the AM/PM node a lot. 1127eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Set up AM and PM to respond to "a" and "p". 1128eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node ampm = new Node(getAmOrPmKeyCode(AM), getAmOrPmKeyCode(PM)); 1129eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1130eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The first hour digit may be 1. 1131eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node firstDigit = new Node(k1); 1132eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mLegalTimesTree.addChild(firstDigit); 1133eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We'll allow quick input of on-the-hour times. E.g. 1pm. 1134eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit.addChild(ampm); 1135eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1136eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 1, the second digit may be 0-2. 1137eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node secondDigit = new Node(k0, k1, k2); 1138eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit.addChild(secondDigit); 1139eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // Also for quick input of on-the-hour times. E.g. 10pm, 12am. 1140eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit.addChild(ampm); 1141eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1142eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 1, and the second digit is 0-2, the third digit may be 0-5. 1143eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node thirdDigit = new Node(k0, k1, k2, k3, k4, k5); 1144eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit.addChild(thirdDigit); 1145eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The time may be finished now. E.g. 1:02pm, 1:25am. 1146eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio thirdDigit.addChild(ampm); 1147eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1148eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 1, the second digit is 0-2, and the third digit is 0-5, 1149eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // the fourth digit may be 0-9. 1150eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio Node fourthDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); 1151eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio thirdDigit.addChild(fourthDigit); 1152eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The time must be finished now. E.g. 10:49am, 12:40pm. 1153eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio fourthDigit.addChild(ampm); 1154eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1155eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 1, and the second digit is 0-2, the third digit may be 6-9. 1156eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio thirdDigit = new Node(k6, k7, k8, k9); 1157eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit.addChild(thirdDigit); 1158eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The time must be finished now. E.g. 1:08am, 1:26pm. 1159eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio thirdDigit.addChild(ampm); 1160eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1161eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 1, the second digit may be 3-5. 1162eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit = new Node(k3, k4, k5); 1163eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit.addChild(secondDigit); 1164eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1165eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 1, and the second digit is 3-5, the third digit may be 0-9. 1166eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); 1167eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit.addChild(thirdDigit); 1168eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The time must be finished now. E.g. 1:39am, 1:50pm. 1169eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio thirdDigit.addChild(ampm); 1170eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1171eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The hour digit may be 2-9. 1172eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit = new Node(k2, k3, k4, k5, k6, k7, k8, k9); 1173eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mLegalTimesTree.addChild(firstDigit); 1174eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // We'll allow quick input of on-the-hour-times. E.g. 2am, 5pm. 1175eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit.addChild(ampm); 1176eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1177eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 2-9, the second digit may be 0-5. 1178eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit = new Node(k0, k1, k2, k3, k4, k5); 1179eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio firstDigit.addChild(secondDigit); 1180eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1181eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // When the first digit is 2-9, and the second digit is 0-5, the third digit may be 0-9. 1182eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); 1183eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio secondDigit.addChild(thirdDigit); 1184eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio // The time must be finished now. E.g. 2:57am, 9:30pm. 1185eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio thirdDigit.addChild(ampm); 1186eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1187eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1188eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1189eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio /** 1190eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * Simple node class to be used for traversal to check for legal times. 1191eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * mLegalKeys represents the keys that can be typed to get to the node. 1192eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio * mChildren are the children that can be reached from this node. 1193eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio */ 1194eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private class Node { 1195eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private int[] mLegalKeys; 1196eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio private ArrayList<Node> mChildren; 1197eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1198eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public Node(int... legalKeys) { 1199eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mLegalKeys = legalKeys; 1200eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mChildren = new ArrayList<Node>(); 1201eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1202eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1203eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public void addChild(Node child) { 1204eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio mChildren.add(child); 1205eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1206eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1207eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean containsKey(int key) { 1208eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (int i = 0; i < mLegalKeys.length; i++) { 1209eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mLegalKeys[i] == key) { 1210eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return true; 1211eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1212eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1213eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return false; 1214eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1215eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 1216eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public Node canReach(int key) { 1217eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (mChildren == null) { 1218eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return null; 1219eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1220eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio for (Node child : mChildren) { 1221eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (child.containsKey(key)) { 1222eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return child; 1223eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1224eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1225eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return null; 1226eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1227eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1228eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio 122967945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette private final View.OnClickListener mClickListener = new View.OnClickListener() { 123067945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette @Override 123167945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette public void onClick(View v) { 123267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 123367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette final int amOrPm; 123467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette switch (v.getId()) { 123567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette case R.id.am_label: 123667945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette setAmOrPm(AM); 123767945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette break; 123867945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette case R.id.pm_label: 123967945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette setAmOrPm(PM); 124067945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette break; 124167945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette case R.id.hours: 124267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette setCurrentItemShowing(HOUR_INDEX, true, true); 124367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette break; 124467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette case R.id.minutes: 124567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette setCurrentItemShowing(MINUTE_INDEX, true, true); 124667945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette break; 124767945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette default: 124867945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette // Failed to handle this click, don't vibrate. 124967945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette return; 125067945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette } 125167945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 125267945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette tryVibrate(); 125367945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette } 125467945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette }; 125567945c11a5e9547f71be91ceb99e7b9ff15a6292Alan Viverette 1256ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette private final View.OnKeyListener mKeyListener = new View.OnKeyListener() { 1257eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio @Override 1258eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio public boolean onKey(View v, int keyCode, KeyEvent event) { 1259eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio if (event.getAction() == KeyEvent.ACTION_UP) { 1260eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return processKeyUp(keyCode); 1261eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1262eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio return false; 1263eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio } 1264ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette }; 1265ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette 1266ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette private final View.OnFocusChangeListener mFocusListener = new View.OnFocusChangeListener() { 1267ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette @Override 1268ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette public void onFocusChange(View v, boolean hasFocus) { 1269ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette if (!hasFocus && mInKbMode && isTypedTimeFullyLegal()) { 1270ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette finishKbMode(); 1271ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette 1272ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette if (mOnTimeChangedListener != null) { 1273ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette mOnTimeChangedListener.onTimeChanged(mDelegator, 1274ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette mRadialTimePickerView.getCurrentHour(), 1275ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette mRadialTimePickerView.getCurrentMinute()); 1276ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette } 1277ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette } 1278ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette } 1279ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette }; 1280eeff63a5c347f282b5c8c3ae6a0924bf03fbce8fFabrice Di Meglio} 1281