Java tutorial
/* * Copyright 2016 Makoto Consulting Group, 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.makotojava.android.debate; import java.util.ArrayList; import java.util.List; import java.util.Locale; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.NavUtils; import android.util.Log; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.widget.TextView; import com.makotojava.android.debate.SpeechCountDownTimer.SpeechCountDownTimerCallback; import com.makotojava.android.debate.config.SystemOptions; import com.makotojava.android.debate.config.SystemOptionsImpl; import com.makotojava.android.debate.model.PolicySpeech; import com.makotojava.android.debate.model.PolicySpeechFactory; import com.makotojava.android.debate.model.PolicySpeechSingleton; public class PolicySpeechFragment extends Fragment { // private static final boolean _testing = false; // Log TAGs private static final String TAG = PolicySpeechFragment.class.getName(); private static final long NUMBER_OF_MILLIS_IN_ONE_MINUTE = PolicySpeechFactory.NUMBER_OF_MILLIS_IN_ONE_MINUTE; // Property names used to store and retrieve state private static final String CLASS_PREFIX = PolicySpeechFragment.class.getName(); public static final String ARG_INDEX = CLASS_PREFIX + ".ARG_INDEX"; // public static final String CURRENT_STATE = CLASS_PREFIX + ".CURRENT_STATE"; public static final String SPEECH_TIMER = CLASS_PREFIX + ".SPEECH_TIMER"; public static final String CROSSEX_TIMER = CLASS_PREFIX + ".CROSSEX_TIMER"; public static final String AFFPREP_TIMER = CLASS_PREFIX + ".AFFPREP_TIMER"; public static final String NEGPREP_TIMER = CLASS_PREFIX + ".NEGPREP_TIMER"; public static final String MINUTES_SECONDS_PICKER_TITLE = "Select Minutes/Seconds"; public static final int RQID_SPEECHTIMER = 0; public static final int RQID_CROSSEXTIMER = 1; public static final int RQID_AFFPREPTIMER = 2; public static final int RQID_NEGPREPTIMER = 3; private enum STATE { THIS_IS_THE_ACTIVE_SPEECH, NO_ACTIVE_SPEECH, //NEW, //INITIAL, SPEECH_TIMER_RUNNING, SPEECH_TIMER_STOPPED, SPEECH_TIMER_EXHAUSTED, SPEECH_TIMER_SET, CROSSEX_TIMER_RUNNING, CROSSEX_TIMER_STOPPED, CROSSEX_TIMER_EXHAUSTED, CROSSEX_TIMER_SET, AFFPREP_TIMER_RUNNING, AFFPREP_TIMER_STOPPED, AFFPREP_TIMER_EXHAUSTED, AFFPREP_TIMER_SET, NEGPREP_TIMER_RUNNING, NEGPREP_TIMER_STOPPED, NEGPREP_TIMER_EXHAUSTED, NEGPREP_TIMER_SET, // SAVING_INSTANCE_STATE, INSTANCE_STATE_SAVED, INSTANCE_STATE_RESTORED, // TESTING, }; private transient SystemOptions _systemOptions; private SystemOptions getSystemOptions() { if (_systemOptions == null) { _systemOptions = new SystemOptionsImpl(getActivity()); } return _systemOptions; } private PolicySpeechSingleton getPolicySpeechSingleton() { return PolicySpeechSingleton.instance(getActivity()); } private Bundle _savedInstanceState;//workaround @Override public void onSaveInstanceState(Bundle outState) { Log.d(TAG, "saveInstanceState(): Saving Fragment State for Speech => " + _speech); super.onSaveInstanceState(outState); outState.putSerializable(SPEECH_TIMER, _speechTimer); outState.putSerializable(CROSSEX_TIMER, _crossexTimer); outState.putSerializable(AFFPREP_TIMER, getAffirmativePrepTimer()); outState.putSerializable(NEGPREP_TIMER, getNegativePrepTimer()); } private int _speechIndex; private PolicySpeech _speech; // Default onSaveInstanceState() should take care of these private TextView _speechTimerTextView; private TextView _crossexTimerTextView; private TextView _affirmativePrepTimerTextView; private TextView _negativePrepTimerTextView; // // ValueAnimator // private ValueAnimator _valueAnimator; // These, however, we have to save ourselves private SpeechCountDownTimerWithAlarm _speechTimer; private SpeechCountDownTimerWithAlarm _crossexTimer; private SpeechCountDownTimerWithAlarm _affirmativePrepTimer; private SpeechCountDownTimerWithAlarm getAffirmativePrepTimer() { if (_affirmativePrepTimer == null) { _affirmativePrepTimer = createAffPrepCountDownTimer( getPolicySpeechSingleton().getAffirmativePrepRemainingTime()); } return _affirmativePrepTimer; } private SpeechCountDownTimerWithAlarm _negativePrepTimer; private SpeechCountDownTimerWithAlarm getNegativePrepTimer() { if (_negativePrepTimer == null) { _negativePrepTimer = createNegPrepCountDownTimer( getPolicySpeechSingleton().getNegativePrepRemainingTime()); } return _negativePrepTimer; } private View _rootView; private View getRootView() { return _rootView; } private long countdownInterval; private long getCountdownInterval() { countdownInterval = SpeechCountDownTimer.DEFAULT_COUNTDOWN_INTERVAL; if (getSystemOptions().showTenthsOfSeconds()) { countdownInterval = 110; } return countdownInterval; } public static PolicySpeechFragment newInstance(int index) { Log.d(TAG, "newInstance(): index => " + index); PolicySpeechFragment ret = new PolicySpeechFragment(); Bundle fragmentArgs = new Bundle(); fragmentArgs.putInt(ARG_INDEX, index); ret.setArguments(fragmentArgs); return ret; } @Override public void onStop() { super.onStop(); Log.d(TAG, "onStop() for Speech => " + _speech); // NO MEMORY LEAKS, YOU HEAR ME?!?!? if (_speechTimer.isRunning()) _speechTimer.stop(); if (_crossexTimer.isRunning()) _crossexTimer.stop(); if (getAffirmativePrepTimer().isRunning()) getAffirmativePrepTimer().stop(); if (getNegativePrepTimer().isRunning()) getNegativePrepTimer().stop(); } @Override public void onPause() { super.onPause(); Log.d(TAG, "onPause() for Speech => " + _speech); _savedInstanceState = new Bundle(); // This is gross. But unfortunately, onSaveInstanceState() is /// not called for Fragments like it is for Activities onSaveInstanceState(_savedInstanceState); } @Override public void onCreate(Bundle savedInstanceState) { Log.d(TAG, "onCreate() for Speech => " + _speech + ", savedInstanceState => " + savedInstanceState); super.onCreate(savedInstanceState); //setRetainInstance(true);// This Fragment is retained setHasOptionsMenu(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.d(TAG, "onCreateView() for Speech => " + _speech + ", savedInstanceState => " + savedInstanceState); _rootView = inflater.inflate(R.layout.fragment_policy_speech, container, false); // // Enable the app icon getActivity().getActionBar().setDisplayHomeAsUpEnabled(true); // // Bundle fragmentArgs = getArguments(); _speechIndex = fragmentArgs.getInt(ARG_INDEX); _speech = getPolicySpeechSingleton().getSpeechByIndex(_speechIndex); Log.d(TAG, "Speech => " + _speech.getName()); TextView speechTitle = (TextView) getRootView().findViewById(R.id.speechTitle); speechTitle.setText("Speech: " + _speech.getName()); // _speechTimerTextView = createSpeechTimerTextView(getRootView()); // _crossexTimerTextView = createCrossExTimerTextView(getRootView()); if (_speech.getCrossExDurationInMinutes() == 0) { _crossexTimerTextView.setVisibility(View.INVISIBLE); TextView label = (TextView) _rootView.findViewById(R.id.crossExTimerLabel); label.setVisibility(View.INVISIBLE); } // _affirmativePrepTimerTextView = createAffirmativePrepTimerTextView(getRootView()); getAffirmativePrepTimer() .setMillisUntilFinished(getPolicySpeechSingleton().getAffirmativePrepRemainingTime()); // _negativePrepTimerTextView = createNegativePrepTimerTextView(getRootView()); getNegativePrepTimer().setMillisUntilFinished(getPolicySpeechSingleton().getNegativePrepRemainingTime()); // Optimization getSystemOptions().showTenthsOfSeconds();// init // //********** // Now that everything has been set up, let's check and see if /// we are actually recreating an instance of this Fragment, and can /// use savedInstanceState to restore its state // // This is the initial state of a newly created Activity if (_savedInstanceState != null) { restoreInstanceState(_savedInstanceState); } // Manage State manageState(); // return getRootView(); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: // if (NavUtils.getParentActivityName(getActivity()) != null) { NavUtils.navigateUpFromSameTask(getActivity()); } return true; default: return super.onOptionsItemSelected(item); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { // if (resultCode == Activity.RESULT_OK) { long millisUntilFinished = data.getLongExtra(TimePickerFragment.RESULT_MILLIS, 0); Log.d(TAG, "Returned from TimePickerDialog... millis => " + millisUntilFinished); if (requestCode == RQID_SPEECHTIMER) { Log.d(TAG, "Speech Timer"); _speechTimer.setMillisUntilFinished(millisUntilFinished); ; } else if (requestCode == RQID_CROSSEXTIMER) { Log.d(TAG, "CrossEx Timer"); _crossexTimer.setMillisUntilFinished(millisUntilFinished); } else if (requestCode == RQID_AFFPREPTIMER) { Log.d(TAG, "Aff Prep Timer"); getAffirmativePrepTimer().setMillisUntilFinished(millisUntilFinished); getPolicySpeechSingleton().setAffirmativePrepRemainingTime(millisUntilFinished); } else if (requestCode == RQID_NEGPREPTIMER) { Log.d(TAG, "Neg Prep Timer"); getNegativePrepTimer().setMillisUntilFinished(millisUntilFinished); getPolicySpeechSingleton().setNegativePrepRemainingTime(millisUntilFinished); } manageState(); } } /** * New method to handle state management from outside. AFAIK Android * does not offer a method that is invoked when a Fragment inside a * ViewPager becomes the visible page. Not that we would know inside * this class how it is being used, of course. :) */ public void manageState() { Log.d(TAG, "manageState(): HELLO from speech => " + _speech); List<STATE> currentState = computeCurrentState(); for (STATE state : currentState) { adjustAppBasedOnSpecifiedState(state); } updateTimerTextView(_affirmativePrepTimerTextView, getPolicySpeechSingleton().getAffirmativePrepRemainingTime()); updateTimerTextView(_negativePrepTimerTextView, getPolicySpeechSingleton().getNegativePrepRemainingTime()); updateTimerTextView(_speechTimerTextView, _speechTimer.getMillisUntilFinished()); updateTimerTextView(_crossexTimerTextView, _crossexTimer.getMillisUntilFinished()); } private void restoreInstanceState(Bundle savedInstanceState) { Log.d(TAG, "Restoring instance state for Speech => " + _speech); if (savedInstanceState != null) { _speechTimer = (SpeechCountDownTimerWithAlarm) savedInstanceState.getSerializable(SPEECH_TIMER); _crossexTimer = (SpeechCountDownTimerWithAlarm) savedInstanceState.getSerializable(CROSSEX_TIMER); _affirmativePrepTimer = (SpeechCountDownTimerWithAlarm) savedInstanceState .getSerializable(AFFPREP_TIMER); _affirmativePrepTimer .setMillisUntilFinished(getPolicySpeechSingleton().getAffirmativePrepRemainingTime()); _negativePrepTimer = (SpeechCountDownTimerWithAlarm) savedInstanceState.getSerializable(NEGPREP_TIMER); _negativePrepTimer.setMillisUntilFinished(getPolicySpeechSingleton().getNegativePrepRemainingTime()); getSystemOptions();// re-initialize adjustAppBasedOnSpecifiedState(STATE.INSTANCE_STATE_RESTORED); manageState(); } else { Log.i(TAG, "SAVED INSTANCE STATE IS NULL!!"); } } private TextView createSpeechTimerTextView(View rootView) { TextView speechTimer = (TextView) rootView.findViewById(R.id.speechTimer); PolicySpeech speech = getPolicySpeechSingleton().getSpeechByIndex(_speechIndex); long durationInMillis = speech.getDurationInMinutes() * NUMBER_OF_MILLIS_IN_ONE_MINUTE; createSpeechCountDownTimer(durationInMillis); createSpeechTimerOnClickListener(speechTimer); createSpeechTimerOnLongClickListener(speechTimer); return speechTimer; } private TextView createCrossExTimerTextView(View rootView) { TextView speechTimer = (TextView) rootView.findViewById(R.id.crossExTimer); PolicySpeech speech = getPolicySpeechSingleton().getSpeechByIndex(_speechIndex); long durationInMillis = speech.getCrossExDurationInMinutes() * NUMBER_OF_MILLIS_IN_ONE_MINUTE; createCrossExCountDownTimer(durationInMillis); createCrossExTimerOnClickListener(speechTimer); createCrossExTimerOnLongClickListener(speechTimer); return speechTimer; } private TextView createAffirmativePrepTimerTextView(View rootView) { TextView affirmativePrepTimer = (TextView) rootView.findViewById(R.id.affirmativePrepTimer); createAffPrepTimerOnClickListener(affirmativePrepTimer); createAffPrepTimerOnLongClickListener(affirmativePrepTimer); return affirmativePrepTimer; } private TextView createNegativePrepTimerTextView(View rootView) { TextView negativePrepTimer = (TextView) rootView.findViewById(R.id.negativePrepTimer); createNegPrepTimerOnClickListener(negativePrepTimer); createNegPrepTimerOnLongClickListener(negativePrepTimer); return negativePrepTimer; } //************************************** //* Create Timers //************************************** private void createSpeechCountDownTimer(long durationInMillis) { _speechTimer = new SpeechCountDownTimerWithAlarm(durationInMillis, getCountdownInterval(), new SpeechCountDownTimerCallback() { //private static final long serialVersionUID = 1L; @Override public void update(long millisUntilFinished) { updateTimerTextView(_speechTimerTextView, millisUntilFinished); if (getSystemOptions().animateWhenTimerBelowThreshold()) { if (millisUntilFinished < NUMBER_OF_MILLIS_IN_ONE_MINUTE) { if (((millisUntilFinished / 1000) % 60 % 2) == 0) _speechTimerTextView.setTextColor(Color.RED); else _speechTimerTextView.setTextColor(Color.BLACK); } } } @Override public void done() { Log.i(TAG, "Speech Timer is done!"); // Beep or flash or something?? _speechTimer.exhaust(); _speechTimerTextView.setTextColor(Color.RED); if (getSystemOptions().notifyAtTimerExpiration()) { _speechTimer.playNotification(getActivity()); } manageState(); } }); } private void createCrossExCountDownTimer(long durationInMillis) { _crossexTimer = new SpeechCountDownTimerWithAlarm(durationInMillis, getCountdownInterval(), new SpeechCountDownTimerCallback() { //private static final long serialVersionUID = 1L; @Override public void update(long millisUntilFinished) { updateTimerTextView(_crossexTimerTextView, millisUntilFinished); // Animate the timer when < 1 minute to go if (getSystemOptions().animateWhenTimerBelowThreshold()) { if (millisUntilFinished < NUMBER_OF_MILLIS_IN_ONE_MINUTE) { if (((millisUntilFinished / 1000) % 60 % 2) == 0) _crossexTimerTextView.setTextColor(Color.RED); else _crossexTimerTextView.setTextColor(Color.BLACK); } } } @Override public void done() { Log.i(TAG, "Speech Timer is done!"); // Beep or flash or something?? _crossexTimer.exhaust(); if (getSystemOptions().notifyAtTimerExpiration()) { _crossexTimer.playNotification(getActivity()); } _crossexTimerTextView.setTextColor(Color.RED); manageState(); } }); } private SpeechCountDownTimerWithAlarm createAffPrepCountDownTimer(final long durationInMillis) { Log.i(TAG, "Creating Affirmative Prep Timer..."); SpeechCountDownTimerWithAlarm ret = new SpeechCountDownTimerWithAlarm(durationInMillis, getCountdownInterval(), new SpeechCountDownTimerCallback() { //private static final long serialVersionUID = 1L; @Override public void update(long millisUntilFinished) { updateTimerTextView(_affirmativePrepTimerTextView, millisUntilFinished); getPolicySpeechSingleton().setAffirmativePrepRemainingTime(millisUntilFinished); //Log.i(TAG, "Aff Prep Timer, millis to go => " + millisUntilFinished); // Animate the timer when < 1 minute to go if (getSystemOptions().animateWhenTimerBelowThreshold()) { if (millisUntilFinished < NUMBER_OF_MILLIS_IN_ONE_MINUTE) { if (((millisUntilFinished / 1000) % 60 % 2) == 0) _affirmativePrepTimerTextView.setTextColor(Color.RED); else _affirmativePrepTimerTextView.setTextColor(Color.BLACK); } } } @Override public void done() { Log.i(TAG, "Affirmative Prep Timer is done!"); getPolicySpeechSingleton().setAffirmativePrepRemainingTime(0); getAffirmativePrepTimer().exhaust(); if (getSystemOptions().notifyAtTimerExpiration()) { getAffirmativePrepTimer().playNotification(getActivity()); } _affirmativePrepTimerTextView.setTextColor(Color.RED); manageState(); } }); return ret; } private SpeechCountDownTimerWithAlarm createNegPrepCountDownTimer(final long durationInMillis) { Log.i(TAG, "Creating Negative Prep Timer..."); SpeechCountDownTimerWithAlarm ret = new SpeechCountDownTimerWithAlarm(durationInMillis, getCountdownInterval(), new SpeechCountDownTimerCallback() { //private static final long serialVersionUID = 1L; @Override public void update(long millisUntilFinished) { updateTimerTextView(_negativePrepTimerTextView, millisUntilFinished); getPolicySpeechSingleton().setNegativePrepRemainingTime(millisUntilFinished); // Animate the timer when < 1 minute to go if (getSystemOptions().animateWhenTimerBelowThreshold()) { if (millisUntilFinished < NUMBER_OF_MILLIS_IN_ONE_MINUTE) { if (((millisUntilFinished / 1000) % 60 % 2) == 0) _negativePrepTimerTextView.setTextColor(Color.RED); else _negativePrepTimerTextView.setTextColor(Color.BLACK); } } } @Override public void done() { Log.i(TAG, "Negative Prep Timer is done!"); getPolicySpeechSingleton().setNegativePrepRemainingTime(0); getNegativePrepTimer().exhaust(); if (getSystemOptions().notifyAtTimerExpiration()) { getNegativePrepTimer().playNotification(getActivity()); } _negativePrepTimerTextView.setTextColor(Color.RED); manageState(); } }); return ret; } //************************************** //* Create onClickListeners //************************************** private void createSpeechTimerOnClickListener(TextView speechTimer) { speechTimer.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Toggle Timer state Log.i(TAG, "Speech Timer: Click, speech => " + _speech); if (!_speechTimer.isExhausted()) { if (_speechTimer.isRunning()) { _speechTimer.stop(); manageState(); } else { _speechTimer.go(); manageState(); } } else { if (_speechTimer.isPlayingNotification()) { _speechTimer.stopNotification(getActivity()); } } } }); } private void createCrossExTimerOnClickListener(TextView speechTimer) { speechTimer.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Toggle Timer state Log.i(TAG, "Crossex Timer: Click, speech => " + _speech); if (!_crossexTimer.isExhausted()) { if (_crossexTimer.isRunning()) { _crossexTimer.stop(); manageState(); } else { _crossexTimer.go(); manageState(); } } } }); } private void createAffPrepTimerOnClickListener(TextView affirmativePrepTimer) { affirmativePrepTimer.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Toggle Timer state Log.i(TAG, "Affirmative Prep Timer: Click, speech => " + _speech); if (!getAffirmativePrepTimer().isExhausted()) { if (getAffirmativePrepTimer().isRunning()) { getAffirmativePrepTimer().stop(); manageState(); } else { getAffirmativePrepTimer().setMillisUntilFinished( getPolicySpeechSingleton().getAffirmativePrepRemainingTime()); getAffirmativePrepTimer().go(); manageState(); } } } }); } private void createNegPrepTimerOnClickListener(TextView negativePrepTimer) { negativePrepTimer.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Toggle Timer state Log.i(TAG, "Negative Prep Timer: Click from speech " + _speech); if (!getNegativePrepTimer().isExhausted()) { if (getNegativePrepTimer().isRunning()) { getNegativePrepTimer().stop(); manageState(); } else { getNegativePrepTimer() .setMillisUntilFinished(getPolicySpeechSingleton().getNegativePrepRemainingTime()); getNegativePrepTimer().go(); manageState(); } } } }); } //************************************** //* Create onLongClickListeners //************************************** private void createSpeechTimerOnLongClickListener(TextView speechTimer) { speechTimer.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { getActivity().startActionMode(new ActionMode.Callback() { @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { // Nothing to do } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate the menu MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.speech_timer_context_menu, menu); return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { boolean ret = false; switch (item.getItemId()) { case R.id.speech_context_menu_item_reset: Log.i(TAG, "CONTEXT MENU: Speech Timer **RESET**"); long originalDurationInMillis = _speechTimer.reset(); updateTimerTextView(_speechTimerTextView, originalDurationInMillis); _speechTimerTextView.setTextColor(Color.BLACK); ret = true; break; case R.id.speech_context_menu_item_set: Log.i(TAG, "CONTEXT MENU: Speech Timer **SET**"); // Display dialog to set Timer FragmentManager fragMan = getActivity().getFragmentManager(); TimePickerFragment dialog = TimePickerFragment.newInstance( _speechTimer.getMillisUntilFinished(), _speech.getDurationInMinutes(), RQID_SPEECHTIMER); dialog.setTargetFragment(PolicySpeechFragment.this, 0); dialog.show(fragMan, MINUTES_SECONDS_PICKER_TITLE); _speechTimerTextView.setTextColor(Color.BLACK); ret = true; break; } return ret; } }); return true; } }); } private void createCrossExTimerOnLongClickListener(TextView speechTimer) { speechTimer.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { getActivity().startActionMode(new ActionMode.Callback() { @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { // Nothing to do } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate the menu MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.crossex_timer_context_menu, menu); return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { boolean ret = false; switch (item.getItemId()) { case R.id.crossex_context_menu_reset: Log.i(TAG, "CONTEXT MENU: CrossEx Timer **RESET**"); long originalDurationInMillis = _crossexTimer.reset(); updateTimerTextView(_crossexTimerTextView, originalDurationInMillis); _crossexTimerTextView.setTextColor(Color.BLACK); mode.finish(); ret = true; break; case R.id.crossex_context_menu_set: Log.i(TAG, "CONTEXT MENU: CrossEx Timer **SET**"); // Display dialog to set Timer FragmentManager fragMan = getActivity().getFragmentManager(); TimePickerFragment dialog = TimePickerFragment.newInstance( _crossexTimer.getMillisUntilFinished(), _speech.getCrossExDurationInMinutes(), RQID_CROSSEXTIMER); dialog.setTargetFragment(PolicySpeechFragment.this, 0); dialog.show(fragMan, MINUTES_SECONDS_PICKER_TITLE); _crossexTimerTextView.setTextColor(Color.BLACK); mode.finish(); ret = true; break; } return ret; } }); return true; } }); } private void createAffPrepTimerOnLongClickListener(TextView speechTimer) { speechTimer.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { getActivity().startActionMode(new ActionMode.Callback() { @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { // Nothing to do } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate the menu MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.affprep_timer_context_menu, menu); return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { boolean ret = false; switch (item.getItemId()) { case R.id.affprep_context_menu_reset: Log.i(TAG, "CONTEXT MENU: Aff Prep Timer **RESET**"); long originalDurationInMillis = getAffirmativePrepTimer().reset(); updateTimerTextView(_affirmativePrepTimerTextView, originalDurationInMillis); getPolicySpeechSingleton().setAffirmativePrepRemainingTime(originalDurationInMillis); _affirmativePrepTimerTextView.setTextColor(Color.BLACK); ret = true; break; case R.id.affprep_context_menu_set: Log.i(TAG, "CONTEXT MENU: Aff Prep Timer **SET**"); // Display dialog to set Timer FragmentManager fragMan = getActivity().getFragmentManager(); TimePickerFragment dialog = TimePickerFragment.newInstance( getAffirmativePrepTimer().getMillisUntilFinished(), PolicySpeechFactory.PREP_TIME_IN_MINUTES, RQID_AFFPREPTIMER); dialog.setTargetFragment(PolicySpeechFragment.this, 0); dialog.show(fragMan, MINUTES_SECONDS_PICKER_TITLE); _affirmativePrepTimerTextView.setTextColor(Color.BLACK); ret = true; break; } return ret; } }); return true; } }); } private void createNegPrepTimerOnLongClickListener(TextView speechTimer) { speechTimer.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { getActivity().startActionMode(new ActionMode.Callback() { @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { // Nothing to do } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate the menu MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.negprep_timer_context_menu, menu); return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { boolean ret = false; switch (item.getItemId()) { case R.id.negprep_context_menu_reset: Log.i(TAG, "CONTEXT MENU: Neg Prep Timer **RESET**"); long originalDurationInMillis = getNegativePrepTimer().reset(); updateTimerTextView(_negativePrepTimerTextView, originalDurationInMillis); getPolicySpeechSingleton().setNegativePrepRemainingTime(originalDurationInMillis); _negativePrepTimerTextView.setTextColor(Color.BLACK); ret = true; break; case R.id.negprep_context_menu_set: Log.i(TAG, "CONTEXT MENU: Neg Prep Timer **SET**"); // Display dialog to set Timer FragmentManager fragMan = getActivity().getFragmentManager(); TimePickerFragment dialog = TimePickerFragment.newInstance( getNegativePrepTimer().getMillisUntilFinished(), PolicySpeechFactory.PREP_TIME_IN_MINUTES, RQID_NEGPREPTIMER); dialog.setTargetFragment(PolicySpeechFragment.this, 0); dialog.show(fragMan, MINUTES_SECONDS_PICKER_TITLE); _negativePrepTimerTextView.setTextColor(Color.BLACK); ret = true; break; } return ret; } }); return true; } }); } private void updateTimerTextView(TextView textView, long durationInMillis) { long seconds = (durationInMillis / 1000) % 60; long minutes = (durationInMillis / NUMBER_OF_MILLIS_IN_ONE_MINUTE) % 60; String value; if (getSystemOptions().showTenthsOfSeconds()) { long tenths = (durationInMillis / 100) % 10; value = String.format(Locale.getDefault(), "%d:%02d.%d", minutes, seconds, tenths); } else { value = String.format(Locale.getDefault(), "%d:%02d", minutes, seconds); } textView.setText(value); } private List<STATE> computeCurrentState() { List<STATE> states = new ArrayList<>(); // TESTING // if (_testing) states.add(STATE.TESTING);// TODO: REMOVE ME computeBasicStates(states); computeHigherStates(states); return states; } /** * Compute the most basic states based on direct attribute values. * * @param states */ private void computeBasicStates(List<STATE> states) { // Aff Prep Timer states if (getAffirmativePrepTimer().isRunning()) states.add(STATE.AFFPREP_TIMER_RUNNING); if (getAffirmativePrepTimer().hasEverBeenStarted() && !getAffirmativePrepTimer().isRunning()) states.add(STATE.AFFPREP_TIMER_STOPPED); if (getAffirmativePrepTimer().isExhausted()) states.add(STATE.AFFPREP_TIMER_EXHAUSTED); // Neg Prep Timer states if (getNegativePrepTimer().isRunning()) states.add(STATE.NEGPREP_TIMER_RUNNING); if (getNegativePrepTimer().hasEverBeenStarted() && !getNegativePrepTimer().isRunning()) states.add(STATE.NEGPREP_TIMER_STOPPED); if (getNegativePrepTimer().isExhausted()) states.add(STATE.NEGPREP_TIMER_EXHAUSTED); // Speech Timer states if (_speechTimer.isRunning()) states.add(STATE.SPEECH_TIMER_RUNNING); if (_speechTimer.hasEverBeenStarted() && !_speechTimer.isRunning()) states.add(STATE.SPEECH_TIMER_STOPPED); if (_speechTimer.isExhausted()) states.add(STATE.SPEECH_TIMER_EXHAUSTED); // Cross Ex Timer states if (_crossexTimer.isRunning()) states.add(STATE.CROSSEX_TIMER_RUNNING); if (_crossexTimer.hasEverBeenStarted() && !_crossexTimer.isRunning()) states.add(STATE.CROSSEX_TIMER_STOPPED); if (_crossexTimer.isExhausted()) states.add(STATE.CROSSEX_TIMER_EXHAUSTED); } /** * Compute higher states based on basic states already in the List * * @param states */ private void computeHigherStates(List<STATE> states) { if (_speechIndex == getPolicySpeechSingleton().getActiveSpeechIndex()) { states.add(STATE.THIS_IS_THE_ACTIVE_SPEECH); } if (states.contains(STATE.THIS_IS_THE_ACTIVE_SPEECH) && !anyTimerActive()) { // This is the active speech and no timers are running. There is no /// active speech in that case. It's wide open. states.add(STATE.NO_ACTIVE_SPEECH); } } private boolean anyTimerActive() { return _speechTimer.isRunning() || _crossexTimer.isRunning() || getAffirmativePrepTimer().isRunning() || getNegativePrepTimer().isRunning(); } private void adjustAppBasedOnSpecifiedState(STATE state) { enableTextViewsBasedOnState(state); setLabelTextBasedOnState(state); } private void enableTextViewsBasedOnState(STATE state) { // WIDE OPEN _speechTimerTextView.setEnabled(true); _crossexTimerTextView.setEnabled(true); _affirmativePrepTimerTextView.setEnabled(true); _negativePrepTimerTextView.setEnabled(true); } private void setLabelTextBasedOnState(STATE state) { if (state == STATE.SPEECH_TIMER_RUNNING) { TextView label = (TextView) getRootView().findViewById(R.id.speechTimerLabel); label.setText(getActivity().getResources().getString(R.string.label_speech_timer) + " (Touch to stop)"); } else if (state == STATE.SPEECH_TIMER_STOPPED) { TextView label = (TextView) getRootView().findViewById(R.id.speechTimerLabel); label.setText( getActivity().getResources().getString(R.string.label_speech_timer) + " (Touch to start)"); } else if (state == STATE.SPEECH_TIMER_EXHAUSTED) { TextView label = (TextView) getRootView().findViewById(R.id.speechTimerLabel); label.setText(getActivity().getResources().getString(R.string.label_speech_timer)); } else if (state == STATE.CROSSEX_TIMER_RUNNING) { TextView label = (TextView) getRootView().findViewById(R.id.crossExTimerLabel); label.setText( getActivity().getResources().getString(R.string.label_crossex_timer) + " (Touch to stop)"); } else if (state == STATE.CROSSEX_TIMER_STOPPED) { TextView label = (TextView) getRootView().findViewById(R.id.crossExTimerLabel); label.setText( getActivity().getResources().getString(R.string.label_crossex_timer) + " (Touch to start)"); } else if (state == STATE.CROSSEX_TIMER_EXHAUSTED) { TextView label = (TextView) getRootView().findViewById(R.id.crossExTimerLabel); label.setText(getActivity().getResources().getString(R.string.label_crossex_timer)); } else if (state == STATE.AFFPREP_TIMER_RUNNING) { TextView label = (TextView) getRootView().findViewById(R.id.affPrepTimerLabel); label.setText( getActivity().getResources().getString(R.string.label_affprep_timer) + " (Touch to stop)"); } else if (state == STATE.AFFPREP_TIMER_STOPPED) { TextView label = (TextView) getRootView().findViewById(R.id.affPrepTimerLabel); label.setText( getActivity().getResources().getString(R.string.label_affprep_timer) + " (Touch to start)"); } else if (state == STATE.AFFPREP_TIMER_EXHAUSTED) { TextView label = (TextView) getRootView().findViewById(R.id.affPrepTimerLabel); label.setText(getActivity().getResources().getString(R.string.label_affprep_timer)); } else if (state == STATE.NEGPREP_TIMER_RUNNING) { TextView label = (TextView) getRootView().findViewById(R.id.negPrepTimerLabel); label.setText( getActivity().getResources().getString(R.string.label_negprep_timer) + " (Touch to stop)"); } else if (state == STATE.NEGPREP_TIMER_STOPPED) { TextView label = (TextView) getRootView().findViewById(R.id.negPrepTimerLabel); label.setText( getActivity().getResources().getString(R.string.label_negprep_timer) + " (Touch to start)"); } else if (state == STATE.NEGPREP_TIMER_EXHAUSTED) { TextView label = (TextView) getRootView().findViewById(R.id.negPrepTimerLabel); label.setText(getActivity().getResources().getString(R.string.label_negprep_timer)); } } @Override public void onAttach(Activity activity) { // TODO Auto-generated method stub super.onAttach(activity); Log.d(TAG, "onAttach() for Speech => " + _speech); } @Override public void onDestroyView() { // TODO Auto-generated method stub super.onDestroyView(); Log.d(TAG, "onDestroyView() for Speech => " + _speech); } @Override public void onDetach() { // TODO Auto-generated method stub super.onDetach(); Log.d(TAG, "onDetach() for Speech => " + _speech); } @Override public void onResume() { // TODO Auto-generated method stub super.onResume(); Log.d(TAG, "onResume() for Speech => " + _speech); } @Override public void onStart() { // TODO Auto-generated method stub super.onStart(); Log.d(TAG, "onStart() for Speech => " + _speech); } //**************************************** //* A T T I C //**************************************** }