blob: 84076de97ae76263a25cd9688f90df5597dc21e5 [file] [log] [blame]
package com.projectara.araepm;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.Switch;
import android.widget.Toast;
public class MainActivity extends Activity
implements AnimationListener, EpmController.EpmChangeCallback {
private static final String TAG = "AraEPM";
//
// The following group of fields are locked by `this'.
//
// Index into {left,right}Side{Attach,Detach}, depending on
// current animation (which we obtain in onAnimationEnd).
//
// If no animation ongoing, this is -1.
private int ivIndex;
// If true, an EPM change is ongoing.
private boolean epmChangeOngoing;
// If false, button clicks will be ignored.
private boolean buttonPressesEnabled;
private ImageView leftSideAttach[];
private ImageView leftSideDetach[];
private ImageView rightSideAttach[];
private ImageView rightSideDetach[];
private Animation leftsideAnimAttach,leftsideAnimDetach;
private Animation rightsideAnimAttach, rightsideAnimDetach;
private EpmController epmController;
private static String EPM_ATTACHED;
private static String EPM_DETACHED;
private static String EPM_ATTACHING;
private static String EPM_DETACHING;
private static String EPM_STATUS_OK;
private static String EPM_STATUS_ERROR;
private static String EPM_STATUS_TIMEOUT;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeImageviewAnimation();
}
private void enableButtonPressesLocked() {
Log.d(TAG, "enabling button presses");
if (ivIndex != -1) {
Log.wtf(TAG, "ivIndex=" + ivIndex + ", expected -1");
}
if (epmChangeOngoing) {
Log.wtf(TAG, "epm change is still ongoing!");
}
buttonPressesEnabled = true;
}
private void disableButtonPressesLocked() {
Log.d(TAG, "disabling button presses");
buttonPressesEnabled = false;
}
@Override
protected void onStart() {
super.onStart();
epmController = new EpmController(this, this);
epmController.start();
EPM_ATTACHED = getString(R.string.epm_attached);
EPM_DETACHED = getString(R.string.epm_detached);
EPM_ATTACHING = getString(R.string.epm_attaching);
EPM_DETACHING = getString(R.string.epm_detaching);
EPM_STATUS_OK = getString(R.string.epm_status_ok);
EPM_STATUS_ERROR = getString(R.string.epm_status_error);
EPM_STATUS_TIMEOUT = getString(R.string.epm_status_timeout);
}
@Override
protected void onStop() {
super.onStop();
epmController.stop();
epmController = null;
}
@Override
public void onAnimationRepeat(Animation animation) {
// nop
}
@Override
public void onAnimationStart(Animation animation) {
// nop
}
@Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "onAnimationEnd");
if (animation == leftsideAnimAttach) {
leftSideDetach[ivIndex].setVisibility(View.GONE);
leftSideAttach[ivIndex].setVisibility(View.VISIBLE);
}
if (animation == leftsideAnimDetach) {
leftSideAttach[ivIndex].setVisibility(View.GONE);
leftSideDetach[ivIndex].setVisibility(View.VISIBLE);
}
if (animation == rightsideAnimAttach) {
rightSideDetach[ivIndex].setVisibility(View.GONE);
rightSideAttach[ivIndex].setVisibility(View.VISIBLE);
}
if (animation == rightsideAnimDetach) {
rightSideAttach[ivIndex].setVisibility(View.GONE);
rightSideDetach[ivIndex].setVisibility(View.VISIBLE);
}
synchronized (this) {
ivIndex = -1;
if (!epmChangeOngoing) {
enableButtonPressesLocked();
}
}
}
@Override
public void onEpmChangeFinished(EpmController.EpmState state,
EpmController.EpmChangeStatus status,
int port) {
Log.d(TAG, "onEpmChangeFinished: state=" + state + ", status=" + status +
", port=" + port);
String s;
switch (state) {
case EPM_ATTACH:
s = EPM_ATTACHED;
break;
case EPM_DETACH:
s = EPM_DETACHED;
break;
default:
Log.wtf(TAG, "can't happen");
s = null;
return;
}
String statusFormat;
switch (status) {
case EPM_OK:
statusFormat = EPM_STATUS_OK;
break;
case EPM_ERROR:
statusFormat = EPM_STATUS_ERROR;
break;
case EPM_TIMEOUT:
statusFormat = EPM_STATUS_TIMEOUT;
break;
default:
Log.wtf(TAG, "can't happen");
statusFormat = null;
return;
}
if (s != null && statusFormat != null) {
int duration = Toast.LENGTH_SHORT;
String text = String.format(statusFormat, s, port);
Toast toast = Toast.makeText(getApplicationContext(), text,
duration);
toast.show();
}
synchronized (this) {
epmChangeOngoing = false;
if (ivIndex == -1) {
enableButtonPressesLocked();
}
}
}
public void initializeImageviewAnimation() {
leftSideAttach = new ImageView[] {
(ImageView) findViewById(R.id.leftside_first_left_dwar_attach),
(ImageView) findViewById(R.id.leftside_2nd_left_dwar_attach),
(ImageView) findViewById(R.id.leftside_3rd_left_dwar_attach),
(ImageView) findViewById(R.id.leftside_4th_left_dwar_attach)};
leftSideDetach = new ImageView[] {
(ImageView) findViewById(R.id.leftside_first_left_dwar_detach),
(ImageView) findViewById(R.id.leftside_2nd_left_dwar_detach),
(ImageView) findViewById(R.id.leftside_3rd_left_dwar_detach),
(ImageView) findViewById(R.id.leftside_4th_left_dwar_detach)};
rightSideAttach = new ImageView[] {
(ImageView) findViewById(R.id.rightside_1st_left_dwar_attach),
(ImageView) findViewById(R.id.rightside_2nd_left_dwar_attach),
(ImageView) findViewById(R.id.rightside_3rd_left_dwar_attach),
(ImageView) findViewById(R.id.rightside_4th_left_dwar_attach)};
rightSideDetach = new ImageView[] {
(ImageView) findViewById(R.id.rightside_1st_left_dwar_detach),
(ImageView) findViewById(R.id.rightside_2nd_left_dwar_detach),
(ImageView) findViewById(R.id.rightside_3rd_left_dwar_detach),
(ImageView) findViewById(R.id.rightside_4th_left_dwar_detach)};
// Load animations and set listener.
leftsideAnimAttach = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.leftside_move_leftside);
leftsideAnimDetach = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.leftside_move_rightside);
rightsideAnimAttach = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.move_right_rightside);
rightsideAnimDetach = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.move_right_leftside);
leftsideAnimAttach.setAnimationListener(this);
leftsideAnimDetach.setAnimationListener(this);
rightsideAnimAttach.setAnimationListener(this);
rightsideAnimDetach.setAnimationListener(this);
// All set; initialize EPM image views and event handling.
for (int i = 0; i < leftSideAttach.length; i++) {
ImageView iv = leftSideAttach[i];
iv.setVisibility(View.GONE);
iv.setOnClickListener(new EpmButtonClickListener(iv, true, i, true));
}
for (int i = 0; i < rightSideAttach.length; i++) {
ImageView iv = rightSideAttach[i];
iv.setVisibility(View.GONE);
iv.setOnClickListener(new EpmButtonClickListener(iv, false, i, true));
}
for (int i = 0; i < leftSideDetach.length; i++) {
ImageView iv = leftSideDetach[i];
iv.setOnClickListener(new EpmButtonClickListener(iv, true, i, false));
}
for (int i = 0; i < rightSideDetach.length; i++) {
ImageView iv = rightSideDetach[i];
iv.setOnClickListener(new EpmButtonClickListener(iv, false, i, false));
}
synchronized (this) {
ivIndex = -1;
epmChangeOngoing = false;
enableButtonPressesLocked();
}
}
class EpmButtonClickListener implements View.OnClickListener {
private ImageView iv;
private boolean isLeft;
private int index;
private boolean isAttach;
/**
* Handles EPM changes and mutual exclusion between buttons.
*
* Example arguments for a button listener to attach the top
* left EPM, when endo is viewed from rear:
*
* - iv=(the button)
* - isLeft=true
* - index=0
* - isAttach=true
*
* @param iv The ImageView clicked.
* @param isLeft Is the button on the left side of the endo,
* when viewed from the rear?
* @param index Zero-indexed button number, from endo top
* @param attach Should the button, when clicked, attach the EPM?
*/
public EpmButtonClickListener(ImageView iv, boolean isLeft,
int index, boolean isAttach) {
this.iv = iv;
this.isLeft = isLeft;
this.index = index;
this.isAttach = isAttach;
}
@Override
public String toString() {
return "EpmButtonClickListener(iv=" + iv + ", isLeft=" + isLeft +
", index=" + index + ",isAttach=" + isAttach + ")";
}
@Override
public void onClick(View v) {
Log.d(TAG, "onClick() handler called on: " +
EpmButtonClickListener.this.toString());
int port = getPort();
if (port == -1) {
Log.e(TAG, "onClick: invalid state");
return;
}
// Enforce a single animation per EPM change.
synchronized (MainActivity.this) {
if (!buttonPressesEnabled) {
Log.d(TAG, "Ignoring click while EPM change is ongoing");
return;
} else {
ivIndex = index;
epmChangeOngoing = true;
disableButtonPressesLocked();
}
}
iv.clearAnimation();
Log.i(TAG,
(isAttach ? "Attaching " : "Detaching ") +
" EPM on port " + port);
if (isAttach) {
epmController.attachEpm(port);
} else {
epmController.detachEpm(port);
}
// (The animations have confusing names.)
if (isLeft) {
if (isAttach) {
v.startAnimation(leftsideAnimDetach);
} else {
v.startAnimation(leftsideAnimAttach);
}
} else {
if (isAttach) {
v.startAnimation(rightsideAnimDetach);
} else {
v.startAnimation(rightsideAnimAttach);
}
}
Log.d(TAG, "onClick() handler finished");
}
// The layout, ignoring the buttons that are occupied by the
// switch (marked XX), looks like this, with port numbers
// underneath:
//
// +-----------------------+
// | | R1 |
// | L1 | 4 |
// | 3 +---------------+
// | | |
// | | |
// +-------+ R2 +
// | | 2 |
// | L2 | |
// | 1 +---------------+
// | | |
// | | |
// +-------+ R3 +
// | | 0 |
// | XX | |
// | +---------------+
// | | XX |
// | | |
// +-----------------------+
private int getPort() {
if (isLeft) {
switch (index) {
case 0:
return 3;
case 1:
return 1;
default:
return -1;
}
} else {
switch (index) {
case 0:
return 4;
case 1:
return 2;
case 2:
return 0;
default:
return -1;
}
}
}
}
}