Commit 7b81f762 authored by Geoffrey Métais's avatar Geoffrey Métais

Refactor Time Pickers

- split dialogs in children classes
- handle sign for delay
- work in µSeconds
parent f35f22f7
......@@ -14,26 +14,37 @@
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/jump_dialog_title">
android:layout_below="@+id/jump_dialog_title"
android:layout_centerHorizontal="true">
<Button
android:id="@+id/jump_sign"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:nextFocusRight="@+id/jump_hours"
android:text="+"
android:visibility="gone"/>
<LinearLayout
android:id="@+id/jump_hours_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/jump_sign"
android:orientation="vertical">
<ImageView
android:id="@+id/jump_hours_up"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@android:drawable/arrow_up_float"/>
<EditText
<TextView
android:id="@+id/jump_hours"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="number"
android:layout_margin="5dp"
android:maxLength="2"
android:text="00"
android:focusable="true"
android:nextFocusRight="@+id/jump_minutes"/>
android:nextFocusRight="@+id/jump_minutes"
android:nextFocusLeft="@+id/jump_sign"/>
<ImageView
android:id="@+id/jump_hours_down"
android:layout_width="match_parent"
......@@ -62,13 +73,13 @@
android:layout_height="wrap_content"
android:focusable="true"
android:src="@android:drawable/arrow_up_float"/>
<EditText
<TextView
android:id="@+id/jump_minutes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:nextFocusLeft="@+id/jump_hours"
android:nextFocusRight="@+id/jump_seconds"
android:inputType="number"
android:maxLength="2"
android:text="00"
android:focusable="true"/>
......@@ -100,18 +111,19 @@
android:layout_height="wrap_content"
android:focusable="true"
android:src="@android:drawable/arrow_up_float"/>
<EditText
<TextView
android:id="@+id/jump_seconds"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:nextFocusLeft="@+id/jump_minutes"
android:nextFocusRight="@+id/jump_go"
android:inputType="number"
android:nextFocusRight="@+id/jump_millis"
android:maxLength="2"
android:text="00"
android:textColor="@color/darkorange"
android:focusable="true">
<requestFocus />
</EditText>
</TextView>
<ImageView
android:id="@+id/jump_seconds_down"
android:layout_width="match_parent"
......@@ -119,13 +131,62 @@
android:focusable="true"
android:src="@android:drawable/arrow_down_float"/>
</LinearLayout>
<TextView
android:id="@+id/jump_seconds_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/jump_seconds_container"
android:layout_alignTop="@+id/jump_seconds_container"
android:layout_alignBottom="@+id/jump_seconds_container"
android:gravity="center_vertical"
android:text="s"/>
<LinearLayout
android:id="@+id/jump_millis_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/jump_seconds_text"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:id="@+id/jump_millis_up"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:src="@android:drawable/arrow_up_float"/>
<TextView
android:id="@+id/jump_millis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:nextFocusLeft="@+id/jump_seconds"
android:nextFocusRight="@+id/jump_go"
android:maxLength="3"
android:text="000"
android:focusable="true"/>
<ImageView
android:id="@+id/jump_millis_down"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:src="@android:drawable/arrow_down_float"/>
</LinearLayout>
<TextView
android:id="@+id/jump_millis_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/jump_millis_container"
android:layout_alignTop="@+id/jump_millis_container"
android:layout_alignBottom="@+id/jump_millis_container"
android:gravity="center_vertical"
android:text="ms"
android:visibility="gone"/>
<Button
android:id="@+id/jump_go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@+id/jump_seconds"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/jump_seconds_container"
android:layout_toRightOf="@+id/jump_millis_text"
android:text="@android:string/ok"/>
</RelativeLayout>
</RelativeLayout>
/*
* *************************************************************************
* AudioDelayDialog.java
* **************************************************************************
* Copyright © 2015 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* ***************************************************************************
*/
package org.videolan.vlc.gui.dialogs;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.videolan.vlc.R;
public class AudioDelayDialog extends PickTimeFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
view.findViewById(R.id.jump_millis_container).setVisibility(View.VISIBLE);
view.findViewById(R.id.jump_millis_text).setVisibility(View.VISIBLE);
view.findViewById(R.id.jump_hours_text).setVisibility(View.GONE);
view.findViewById(R.id.jump_hours_container).setVisibility(View.GONE);
mMillis.setOnFocusChangeListener(this);
mMillis.setOnEditorActionListener(this);
mMinutes.setNextFocusLeftId(R.id.jump_sign);
mActionButton.setNextFocusLeftId(R.id.jump_millis);
mSign.setNextFocusRightId(R.id.jump_minutes);
mSign.setVisibility(View.VISIBLE);
mSign.setOnClickListener(this);
mActionButton.setText(android.R.string.cancel);
long delay = mLibVLC.getAudioDelay();
initTime(delay);
return view;
}
@Override
protected void executeAction(){
long minutes = Long.parseLong(mMinutes.getText().toString());
long seconds = Long.parseLong(mSeconds.getText().toString());
long millis = Long.parseLong(mMillis.getText().toString());
long delay = minutes * MINUTES_IN_MICROS + seconds * SECONDS_IN_MICROS + millis * MILLIS_IN_MICROS;
if (mSign.getText().equals("-"))
delay = -delay;
mLibVLC.setAudioDelay(delay);
Log.d(TAG, "setting audio delay to: " + delay);
}
@Override
protected void buttonAction() {
initTime(0l);
executeAction();
}
@Override
protected int getTitle() {
return R.string.audio_delay;
}
}
/*
* *************************************************************************
* JumpToTimeDIalog.java
* **************************************************************************
* Copyright © 2015 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* ***************************************************************************
*/
package org.videolan.vlc.gui.dialogs;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.videolan.libvlc.LibVLC;
import org.videolan.vlc.R;
public class JumpToTimeDialog extends PickTimeFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
if (mLibVLC.getLength() > HOURS_IN_MICROS) {
mHours.setOnFocusChangeListener(this);
mHours.setOnEditorActionListener(this);
view.findViewById(R.id.jump_hours_up).setOnClickListener(this);
view.findViewById(R.id.jump_hours_down).setOnClickListener(this);
} else {
view.findViewById(R.id.jump_hours_text).setVisibility(View.GONE);
view.findViewById(R.id.jump_hours_container).setVisibility(View.GONE);
}
mMinutes.setNextFocusLeftId(R.id.jump_minutes);
mSeconds.setNextFocusRightId(R.id.jump_go);
return view;
}
protected void executeAction() {
long hours = mHours != null ? Long.parseLong(mHours.getText().toString()) * HOURS_IN_MICROS : 0l;
long minutes = Long.parseLong(mMinutes.getText().toString()) * MINUTES_IN_MICROS ;
long seconds = Long.parseLong(mSeconds.getText().toString()) * SECONDS_IN_MICROS;
LibVLC.getExistingInstance().setTime((hours + minutes + seconds)/1000l); //Time in ms
dismiss();
}
@Override
protected void buttonAction() {
executeAction();
}
@Override
protected int getTitle() {
return R.string.jump_to_time;
}
}
......@@ -19,40 +19,40 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* ***************************************************************************
*/
package org.videolan.vlc.gui;
package org.videolan.vlc.gui.dialogs;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.EditText;
import android.widget.Button;
import android.widget.TextView;
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.LibVlcException;
import org.videolan.vlc.R;
public class PickTimeFragment extends DialogFragment implements DialogInterface.OnKeyListener, View.OnClickListener, View.OnFocusChangeListener, TextView.OnEditorActionListener {
public abstract class PickTimeFragment extends DialogFragment implements DialogInterface.OnKeyListener, View.OnClickListener, View.OnFocusChangeListener, TextView.OnEditorActionListener {
public final static String TAG = "VLC/PickTimeFragment";
public static String ACTION = "action";
public static int ACTION_JUMP_TO_TIME = 0;
public static int ACTION_SPU_DELAY = 1;
public static int ACTION_AUDIO_DELAY = 2;
private int mAction = -1;
public static final int ACTION_JUMP_TO_TIME = 0;
public static final int ACTION_SPU_DELAY = 1;
public static final int ACTION_AUDIO_DELAY = 2;
protected int mTextColor;
private static long SECONDS_IN_MICROS = 1000000;
private static long MINUTES_IN_MICROS = 60*SECONDS_IN_MICROS;
private static long HOURS_IN_MICROS = 60*MINUTES_IN_MICROS;
protected static long MILLIS_IN_MICROS = 1000;
protected static long SECONDS_IN_MICROS = 1000 * MILLIS_IN_MICROS;
protected static long MINUTES_IN_MICROS = 60*SECONDS_IN_MICROS;
protected static long HOURS_IN_MICROS = 60*MINUTES_IN_MICROS;
LibVLC mLibVLC = null;
EditText mHours, mMinutes, mSeconds;
protected LibVLC mLibVLC = null;
protected TextView mHours, mMinutes, mSeconds, mMillis;
protected Button mActionButton, mSign;
public PickTimeFragment(){}
......@@ -64,11 +64,14 @@ public class PickTimeFragment extends DialogFragment implements DialogInterface.
} catch (LibVlcException e) {
getDialog().dismiss();
}
mAction = getArguments().getInt(ACTION);
View view = inflater.inflate(R.layout.jump_to_time, container);
((TextView)view.findViewById(R.id.jump_dialog_title)).setText(getTitle());
mMinutes = (EditText) view.findViewById(R.id.jump_minutes);
mSeconds = (EditText) view.findViewById(R.id.jump_seconds);
mHours = (TextView) view.findViewById(R.id.jump_hours);
mMinutes = (TextView) view.findViewById(R.id.jump_minutes);
mSeconds = (TextView) view.findViewById(R.id.jump_seconds);
mMillis = (TextView) view.findViewById(R.id.jump_millis);
mActionButton = (Button) view.findViewById(R.id.jump_go);
mSign = (Button) view.findViewById(R.id.jump_sign);
mMinutes.setOnFocusChangeListener(this);
mSeconds.setOnFocusChangeListener(this);
......@@ -76,30 +79,9 @@ public class PickTimeFragment extends DialogFragment implements DialogInterface.
mMinutes.setOnEditorActionListener(this);
mSeconds.setOnEditorActionListener(this);
if (mAction == ACTION_JUMP_TO_TIME) {
if (mLibVLC.getLength() > HOURS_IN_MICROS) {
mHours = (EditText) view.findViewById(R.id.jump_hours);
mHours.setOnFocusChangeListener(this);
mHours.setOnEditorActionListener(this);
view.findViewById(R.id.jump_hours_up).setOnClickListener(this);
view.findViewById(R.id.jump_hours_down).setOnClickListener(this);
} else {
view.findViewById(R.id.jump_hours_text).setVisibility(View.GONE);
view.findViewById(R.id.jump_hours_container).setVisibility(View.GONE);
}
view.findViewById(R.id.jump_go).setOnClickListener(this);
} else {
view.findViewById(R.id.jump_hours_text).setVisibility(View.GONE);
view.findViewById(R.id.jump_hours_container).setVisibility(View.GONE);
view.findViewById(R.id.jump_go).setVisibility(View.GONE);
long delay = 0l;
if (mAction == ACTION_AUDIO_DELAY)
delay = mLibVLC.getAudioDelay();
else if (mAction == ACTION_SPU_DELAY)
delay = mLibVLC.getSpuDelay();
if (delay != 0f)
initTime(delay);
}
mActionButton.setOnClickListener(this);
mTextColor = mMinutes.getCurrentTextColor();
view.findViewById(R.id.jump_minutes_up).setOnClickListener(this);
view.findViewById(R.id.jump_minutes_down).setOnClickListener(this);
......@@ -115,7 +97,7 @@ public class PickTimeFragment extends DialogFragment implements DialogInterface.
@Override
public void onFocusChange(View v, boolean hasFocus) {
((EditText)v).setSelection(((EditText)v).getText().length());
((TextView)v).setTextColor(hasFocus ? getResources().getColor(R.color.darkorange) : mTextColor);
}
@Override
......@@ -127,10 +109,10 @@ public class PickTimeFragment extends DialogFragment implements DialogInterface.
case KeyEvent.KEYCODE_DPAD_DOWN:
updateViews(keyCode);
return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_NUMPAD_ENTER:
dismiss();
// case KeyEvent.KEYCODE_DPAD_CENTER:
// case KeyEvent.KEYCODE_ENTER:
// case KeyEvent.KEYCODE_NUMPAD_ENTER:
// executeAction();
}
return false;
}
......@@ -156,28 +138,49 @@ public class PickTimeFragment extends DialogFragment implements DialogInterface.
case R.id.jump_seconds_down:
updateValue(-1, R.id.jump_seconds);
break;
case R.id.jump_millis_up:
updateValue(50, R.id.jump_millis);
break;
case R.id.jump_millis_down:
updateValue(-50, R.id.jump_millis);
break;
case R.id.jump_go:
jumpToTime();
buttonAction();
break;
case R.id.jump_sign:
toggleSign();
executeAction();
break;
}
}
private void toggleSign() {
if (mSign.getText().equals("+"))
mSign.setText("-");
else
mSign.setText("+");
}
private void updateViews(int keyCode){
int delta = keyCode == KeyEvent.KEYCODE_DPAD_UP ? 1 : -1;
int id = 0;
if (mSeconds.hasFocus())
if (mMillis.hasFocus()) {
id = mMillis.getId();
delta = keyCode == KeyEvent.KEYCODE_DPAD_UP ? 50 : -50;
} else if (mSeconds.hasFocus())
id = mSeconds.getId();
else if (mMinutes.hasFocus())
id = mMinutes.getId();
else if (mHours != null && mHours.hasFocus())
else if (mHours.hasFocus())
id = mHours.getId();
updateValue(delta, id);
}
private void updateValue(int delta, int resId) {
int max = 59, min = -59;
long length = mLibVLC.getLength();
EditText edit = null;
int max = 59;
String format = "%02d";
long length = mLibVLC.getLength() * 1000; //work in µSeconds
TextView edit = null;
switch(resId){
case R.id.jump_hours:
edit = mHours;
......@@ -186,83 +189,68 @@ public class PickTimeFragment extends DialogFragment implements DialogInterface.
break;
case R.id.jump_minutes:
edit = mMinutes;
if (mAction == ACTION_JUMP_TO_TIME) {
if (this instanceof JumpToTimeDialog) {
if (mHours != null)
length -= Long.decode(mHours.getText().toString()).longValue() * HOURS_IN_MICROS;
if (length < 59 * MINUTES_IN_MICROS)
max = (int) (length / MINUTES_IN_MICROS);
min = 0;
}
break;
case R.id.jump_seconds:
if (mAction == ACTION_JUMP_TO_TIME) {
edit = mSeconds;
if (this instanceof JumpToTimeDialog) {
if (mHours != null)
length -= Long.decode(mHours.getText().toString()).longValue() * HOURS_IN_MICROS;
length -= Long.decode(mMinutes.getText().toString()).longValue() * MINUTES_IN_MICROS;
if (length < 59000)
max = (int) (length / SECONDS_IN_MICROS);
min = 0;
}
edit = mSeconds;
break;
case R.id.jump_millis:
edit = mMillis;
max = 999;
format = "%03d";
break;
}
if (edit != null) {
int value = Integer.parseInt(edit.getText().toString()) + delta;
if (value < min)
if (value < 0)
value = max;
else if (value > max)
value = min;
edit.setText(String.format("%02d", value));
value = 0;
edit.setText(String.format(format, value));
if (mAction == ACTION_AUDIO_DELAY)
setAudioDelay();
else if (mAction == ACTION_SPU_DELAY)
setSpuDelay();
if (this instanceof AudioDelayDialog || this instanceof SubsDelayDialog)
executeAction();
}
}
private void jumpToTime() {
long hours = mHours != null ? Long.parseLong(mHours.getText().toString()) : 0l;
long minutes = Long.parseLong(mMinutes.getText().toString());
long seconds = Long.parseLong(mSeconds.getText().toString());
LibVLC.getExistingInstance().setTime((hours * HOURS_IN_MICROS +
minutes * MINUTES_IN_MICROS +
seconds * SECONDS_IN_MICROS));
dismiss();
}
private void setSpuDelay(){
long minutes = Long.parseLong(mMinutes.getText().toString());
long seconds = Long.parseLong(mSeconds.getText().toString());
mLibVLC.setSpuDelay(minutes * MINUTES_IN_MICROS + seconds * SECONDS_IN_MICROS);
Log.d(TAG, "setting spu delay to: " + (minutes * MINUTES_IN_MICROS + seconds * SECONDS_IN_MICROS));
}
private void setAudioDelay(){
long minutes = Long.parseLong(mMinutes.getText().toString());
long seconds = Long.parseLong(mSeconds.getText().toString());
mLibVLC.setAudioDelay(minutes * MINUTES_IN_MICROS + seconds * SECONDS_IN_MICROS);
Log.d(TAG, "setting audio delay to: "+(minutes * MINUTES_IN_MICROS + seconds * SECONDS_IN_MICROS));
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
jumpToTime();
executeAction();
return true;
}
private void initTime(long delay) {
long minutes = delay / MINUTES_IN_MICROS;
long seconds = (delay - minutes * MINUTES_IN_MICROS)/ SECONDS_IN_MICROS;
protected void initTime(long delay) {
if (delay < 0l){
delay = -delay;
mSign.setText("-");
} else
mSign.setText("+");
long minutes = 0;
long seconds = 0;
long millis = 0;
if (delay != 0) {
minutes = delay / MINUTES_IN_MICROS;
seconds = (delay - minutes * MINUTES_IN_MICROS)/ SECONDS_IN_MICROS;
millis = (delay - minutes * MINUTES_IN_MICROS - seconds * SECONDS_IN_MICROS)/ MILLIS_IN_MICROS;
}
mMinutes.setText(String.format("%02d", minutes));
mSeconds.setText(String.format("%02d", seconds));
mMillis.setText(String.format("%03d", millis));
}
private int getTitle() {
if (mAction == ACTION_AUDIO_DELAY)
return R.string.audio_delay;
else if (mAction == ACTION_SPU_DELAY)
return R.string.spu_delay;
else
return R.string.jump_to_time;
}
abstract protected int getTitle();
abstract protected void executeAction();
abstract protected void buttonAction();
}
/*
* *************************************************************************
* SubsDelayDialog.java
* **************************************************************************
* Copyright © 2015 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or