-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP: add dialog to adjust the synchronization of text captions
status: ======= * works great - is not yet feature complete * this as-not-yet-modified version of 'MultiFieldTimePickerDialog' - does not: * support negative values * implement NumberPicker.OnValueChangeListener - for any change, immediately call: notifyDateSet() => mListener.onTimeSet(hr, min, sec, ms) - would allow the user to see the updates in realtime and tweak the values interactively alongside video playback based on: ========= https://github.com/chromium/chromium/raw/80.0.3987.137/content/public/android/java/src/org/chromium/content/browser/picker/MultiFieldTimePickerDialog.java https://github.com/chromium/chromium/raw/80.0.3987.137/content/public/android/java/src/org/chromium/content/browser/picker/InputDialogContainer.java https://github.com/chromium/chromium/raw/80.0.3987.137/content/public/android/java/res/layout/multi_field_time_picker_dialog.xml
- Loading branch information
1 parent
cdb3fcb
commit c82ca47
Showing
11 changed files
with
606 additions
and
12 deletions.
There are no files selected for viewing
289 changes: 289 additions & 0 deletions
289
...thub/warren_bank/exoplayer_airplay_receiver/ui/exoplayer2/MultiFieldTimePickerDialog.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,289 @@ | ||
// Copyright 2013 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
package com.github.warren_bank.exoplayer_airplay_receiver.ui.exoplayer2; | ||
|
||
import com.github.warren_bank.exoplayer_airplay_receiver.R; | ||
|
||
import android.app.AlertDialog; | ||
import android.content.Context; | ||
import android.content.DialogInterface; | ||
import android.content.DialogInterface.OnClickListener; | ||
import android.view.LayoutInflater; | ||
import android.view.View; | ||
import android.widget.NumberPicker; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Locale; | ||
|
||
/** | ||
* A time picker dialog with upto 5 number pickers left to right: | ||
* hour, minute, second, milli, AM/PM. | ||
* | ||
* If is24hourFormat is true then AM/PM picker is not displayed and | ||
* hour range is 0..23. Otherwise hour range is 1..12. | ||
* The milli picker is not displayed if step >= SECOND_IN_MILLIS | ||
* The second picker is not displayed if step >= MINUTE_IN_MILLIS. | ||
*/ | ||
public class MultiFieldTimePickerDialog | ||
extends AlertDialog implements OnClickListener { | ||
|
||
private final NumberPicker mHourSpinner; | ||
private final NumberPicker mMinuteSpinner; | ||
private final NumberPicker mSecSpinner; | ||
private final NumberPicker mMilliSpinner; | ||
private final NumberPicker mAmPmSpinner; | ||
private final OnMultiFieldTimeSetListener mListener; | ||
private final int mStep; | ||
private final int mBaseMilli; | ||
private final boolean mIs24hourFormat; | ||
|
||
/** | ||
* Adds an onTimeSet() method. | ||
*/ | ||
public interface OnMultiFieldTimeSetListener { | ||
void onTimeSet(int hourOfDay, int minute, int second, int milli); | ||
} | ||
|
||
private static final int SECOND_IN_MILLIS = 1000; | ||
private static final int MINUTE_IN_MILLIS = 60 * SECOND_IN_MILLIS; | ||
private static final int HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS; | ||
|
||
public MultiFieldTimePickerDialog( | ||
Context context, | ||
int theme, | ||
int hour, int minute, int second, int milli, | ||
int min, int max, int step, boolean is24hourFormat, | ||
OnMultiFieldTimeSetListener listener) { | ||
super(context, theme); | ||
mListener = listener; | ||
mStep = step; | ||
mIs24hourFormat = is24hourFormat; | ||
|
||
if (min >= max) { | ||
min = 0; | ||
max = 24 * HOUR_IN_MILLIS - 1; | ||
} | ||
if (step < 0 || step >= 24 * HOUR_IN_MILLIS) { | ||
step = MINUTE_IN_MILLIS; | ||
} | ||
|
||
LayoutInflater inflater = | ||
(LayoutInflater) context.getSystemService( | ||
Context.LAYOUT_INFLATER_SERVICE); | ||
View view = inflater.inflate(R.layout.multi_field_time_picker_dialog, null); | ||
setView(view); | ||
|
||
mHourSpinner = (NumberPicker) view.findViewById(R.id.hour); | ||
mMinuteSpinner = (NumberPicker) view.findViewById(R.id.minute); | ||
mSecSpinner = (NumberPicker) view.findViewById(R.id.second); | ||
mMilliSpinner = (NumberPicker) view.findViewById(R.id.milli); | ||
mAmPmSpinner = (NumberPicker) view.findViewById(R.id.ampm); | ||
|
||
int minHour = min / HOUR_IN_MILLIS; | ||
int maxHour = max / HOUR_IN_MILLIS; | ||
min -= minHour * HOUR_IN_MILLIS; | ||
max -= maxHour * HOUR_IN_MILLIS; | ||
|
||
if (minHour == maxHour) { | ||
mHourSpinner.setEnabled(false); | ||
hour = minHour; | ||
} | ||
|
||
if (is24hourFormat) { | ||
mAmPmSpinner.setVisibility(View.GONE); | ||
} else { | ||
int minAmPm = minHour / 12; | ||
int maxAmPm = maxHour / 12; | ||
int amPm = hour / 12; | ||
mAmPmSpinner.setMinValue(minAmPm); | ||
mAmPmSpinner.setMaxValue(maxAmPm); | ||
mAmPmSpinner.setDisplayedValues(new String[] { | ||
context.getString(R.string.time_picker_dialog_am), | ||
context.getString(R.string.time_picker_dialog_pm) | ||
}); | ||
|
||
hour %= 12; | ||
if (hour == 0) { | ||
hour = 12; | ||
} | ||
if (minAmPm == maxAmPm) { | ||
mAmPmSpinner.setEnabled(false); | ||
amPm = minAmPm; | ||
|
||
minHour %= 12; | ||
maxHour %= 12; | ||
if (minHour == 0 && maxHour == 0) { | ||
minHour = 12; | ||
maxHour = 12; | ||
} else if (minHour == 0) { | ||
minHour = maxHour; | ||
maxHour = 12; | ||
} else if (maxHour == 0) { | ||
maxHour = 12; | ||
} | ||
} else { | ||
minHour = 1; | ||
maxHour = 12; | ||
} | ||
mAmPmSpinner.setValue(amPm); | ||
} | ||
|
||
if (minHour == maxHour) { | ||
mHourSpinner.setEnabled(false); | ||
} | ||
mHourSpinner.setMinValue(minHour); | ||
mHourSpinner.setMaxValue(maxHour); | ||
mHourSpinner.setValue(hour); | ||
|
||
NumberFormatter twoDigitPaddingFormatter = new NumberFormatter("%02d"); | ||
|
||
int minMinute = min / MINUTE_IN_MILLIS; | ||
int maxMinute = max / MINUTE_IN_MILLIS; | ||
min -= minMinute * MINUTE_IN_MILLIS; | ||
max -= maxMinute * MINUTE_IN_MILLIS; | ||
|
||
if (minHour == maxHour) { | ||
mMinuteSpinner.setMinValue(minMinute); | ||
mMinuteSpinner.setMaxValue(maxMinute); | ||
if (minMinute == maxMinute) { | ||
// Set this otherwise the box is empty until you stroke it. | ||
mMinuteSpinner.setDisplayedValues( | ||
new String[] { twoDigitPaddingFormatter.format(minMinute) }); | ||
mMinuteSpinner.setEnabled(false); | ||
minute = minMinute; | ||
} | ||
} else { | ||
mMinuteSpinner.setMinValue(0); | ||
mMinuteSpinner.setMaxValue(59); | ||
} | ||
|
||
mMinuteSpinner.setValue(minute); | ||
if (step % HOUR_IN_MILLIS == 0) { | ||
mMinuteSpinner.setEnabled(false); | ||
// TODO(tkent): We should set minutes value of | ||
// WebDateTimeChooserParams::stepBase. | ||
mMinuteSpinner.setValue(minMinute); | ||
} | ||
|
||
mMinuteSpinner.setFormatter(twoDigitPaddingFormatter); | ||
|
||
if (step >= MINUTE_IN_MILLIS) { | ||
// Remove the ':' in front of the second spinner as well. | ||
view.findViewById(R.id.second_colon).setVisibility(View.GONE); | ||
mSecSpinner.setVisibility(View.GONE); | ||
} | ||
|
||
int minSecond = min / SECOND_IN_MILLIS; | ||
int maxSecond = max / SECOND_IN_MILLIS; | ||
min -= minSecond * SECOND_IN_MILLIS; | ||
max -= maxSecond * SECOND_IN_MILLIS; | ||
|
||
if (minHour == maxHour && minMinute == maxMinute) { | ||
mSecSpinner.setMinValue(minSecond); | ||
mSecSpinner.setMaxValue(maxSecond); | ||
if (minSecond == maxSecond) { | ||
// Set this otherwise the box is empty until you stroke it. | ||
mSecSpinner.setDisplayedValues( | ||
new String[] { twoDigitPaddingFormatter.format(minSecond) }); | ||
mSecSpinner.setEnabled(false); | ||
second = minSecond; | ||
} | ||
} else { | ||
mSecSpinner.setMinValue(0); | ||
mSecSpinner.setMaxValue(59); | ||
} | ||
|
||
mSecSpinner.setValue(second); | ||
mSecSpinner.setFormatter(twoDigitPaddingFormatter); | ||
|
||
if (step >= SECOND_IN_MILLIS) { | ||
// Remove the '.' in front of the milli spinner as well. | ||
view.findViewById(R.id.second_dot).setVisibility(View.GONE); | ||
mMilliSpinner.setVisibility(View.GONE); | ||
} | ||
|
||
// Round to the nearest step. | ||
milli = ((milli + step / 2) / step) * step; | ||
if (step == 1 || step == 10 || step == 100) { | ||
if (minHour == maxHour && minMinute == maxMinute && minSecond == maxSecond) { | ||
mMilliSpinner.setMinValue(min / step); | ||
mMilliSpinner.setMaxValue(max / step); | ||
|
||
if (min == max) { | ||
mMilliSpinner.setEnabled(false); | ||
milli = min; | ||
} | ||
} else { | ||
mMilliSpinner.setMinValue(0); | ||
mMilliSpinner.setMaxValue(999 / step); | ||
} | ||
|
||
if (step == 1) { | ||
mMilliSpinner.setFormatter(new NumberFormatter("%03d")); | ||
} else if (step == 10) { | ||
mMilliSpinner.setFormatter(new NumberFormatter("%02d")); | ||
} else if (step == 100) { | ||
mMilliSpinner.setFormatter(new NumberFormatter("%d")); | ||
} | ||
mMilliSpinner.setValue(milli / step); | ||
mBaseMilli = 0; | ||
} else if (step < SECOND_IN_MILLIS) { | ||
// Non-decimal step value. | ||
ArrayList<String> strValue = new ArrayList<String>(); | ||
for (int i = min; i < max; i += step) { | ||
strValue.add(String.format(Locale.getDefault(), "%03d", i)); | ||
} | ||
mMilliSpinner.setMinValue(0); | ||
mMilliSpinner.setMaxValue(strValue.size() - 1); | ||
mMilliSpinner.setValue((milli - min) / step); | ||
mMilliSpinner.setDisplayedValues(strValue.toArray(new String[strValue.size()])); | ||
mBaseMilli = min; | ||
} else { | ||
mBaseMilli = 0; | ||
} | ||
} | ||
|
||
@Override | ||
public void onClick(DialogInterface dialog, int which) { | ||
notifyDateSet(); | ||
} | ||
|
||
private void notifyDateSet() { | ||
int hour = getPickerValue(mHourSpinner); | ||
int minute = getPickerValue(mMinuteSpinner); | ||
int sec = getPickerValue(mSecSpinner); | ||
int milli = getPickerValue(mMilliSpinner) * mStep + mBaseMilli; | ||
if (!mIs24hourFormat) { | ||
int ampm = getPickerValue(mAmPmSpinner); | ||
if (hour == 12) { | ||
hour = 0; | ||
} | ||
hour += ampm * 12; | ||
} | ||
mListener.onTimeSet(hour, minute, sec, milli); | ||
} | ||
|
||
/** | ||
* Clear focus before retrieving so that values inserted with | ||
* keyboard are taken into account. | ||
*/ | ||
private int getPickerValue(NumberPicker picker) { | ||
picker.clearFocus(); | ||
return picker.getValue(); | ||
} | ||
|
||
private static class NumberFormatter implements NumberPicker.Formatter { | ||
private final String mFormat; | ||
|
||
NumberFormatter(String format) { | ||
mFormat = format; | ||
} | ||
|
||
@Override | ||
public String format(int value) { | ||
return String.format(Locale.getDefault(), mFormat, value); | ||
} | ||
} | ||
} |
Oops, something went wrong.