| /* |
| * Copyright (C) 2014 Google, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| 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; |
| } |
| } |
| } |
| } |
| } |