package pk.contender.earmouse;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.ToggleButton;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
* Fragment for setting up and handling events for a grid of Button objects that represent the possible
* answers of an {@link pk.contender.earmouse.Exercise}.
*
* @author Paul Klinkenberg <pklinken.development@gmail.com>
*/
public class ButtonGridFragment extends Fragment {
/* SharedPreferences constants */
private static final String PREFERENCES_MFADEDBUTTONLIST = "preferences_mFadedButtonList";
private static final String PREFERENCES_MANSWERLIST = "preferences_mAnswerList";
private static AnswerSelectedListener asListener;
private static PracticeModeToggleListener pmListener;
/** The maximum width of the button grid */
private static final int COLUMNS = 3;
private Context mCtx;
/** Basic layout that will contain the {@link android.widget.TableLayout} */
private LinearLayout base;
/** TableLayout that will contain as many {@link android.widget.TableRow} children as necessary */
private TableLayout tl;
/** List of answers to be displayed on the buttons. */
private List<String> mAnswerList = null;
/** List of buttons that are currently faded out, used for state management */
private List<Integer> mFadedButtonList = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCtx = getActivity();
if(mCtx == null)
Log.d("DEBUG", "Context is null in ButtonGrid onCreate()");
}
/**
* On view creation load any saved state and reconstruct the UI how we left it.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_buttongrid, container, false);
base = (LinearLayout) view.findViewById(R.id.grid_base);
ToggleButton toggleButton = (ToggleButton) view.findViewById(R.id.toggleButton);
toggleButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
pmListener.onPracticeModeToggle();
}
});
SharedPreferences settings = mCtx.getSharedPreferences(Main.PREFS_NAME, Activity.MODE_PRIVATE);
Gson gson = new Gson();
Type listType = new TypeToken<ArrayList<String>>() {}.getType();
mAnswerList = gson.fromJson(settings.getString(PREFERENCES_MANSWERLIST, null), listType);
listType = new TypeToken<ArrayList<Integer>>() {}.getType();
mFadedButtonList = gson.fromJson(settings.getString(PREFERENCES_MFADEDBUTTONLIST, null), listType);
if (mAnswerList != null)
buildGrid();
if (mFadedButtonList != null && tl != null) {
for (Integer i : mFadedButtonList) {
Button b = (Button)tl.findViewById(i);
if(b != null) {
b.setAlpha((float) 0.2);
b.setClickable(false);
}
}
}
// Default is Answer mode, corresponding with ExerciseFragment default practiceMode being false.
boolean practiceMode = settings.getBoolean(ExerciseFragment.PREFERENCES_PRACTICEMODE, false);
toggleButton.setChecked(!practiceMode);
return view;
}
/**
* Override to ensure the Activity we are attached to implements {@link pk.contender.earmouse.ButtonGridFragment.AnswerSelectedListener}
* @see AnswerSelectedListener
* @param activity The activity this fragment is attached to.
*/
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof AnswerSelectedListener) {
asListener = (AnswerSelectedListener) activity;
} else {
throw new ClassCastException(activity.toString()
+ " must implement ButtonGridFragment.AnswerSelectedListener");
}
if (activity instanceof PracticeModeToggleListener) {
pmListener = (PracticeModeToggleListener) activity;
} else {
throw new ClassCastException(activity.toString()
+ " must implement ButtonGridFragment.PracticeModeListener");
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
SharedPreferences settings = mCtx.getSharedPreferences(Main.PREFS_NAME, Activity.MODE_PRIVATE);
Gson gson = new Gson();
settings.edit().putString(PREFERENCES_MANSWERLIST, gson.toJson(mAnswerList))
.putString(PREFERENCES_MFADEDBUTTONLIST, gson.toJson(mFadedButtonList)).apply();
super.onSaveInstanceState(outState);
}
/**
* Listener interface for Button clicks, any Activity that attaches this Fragment must implement this.
*/
public interface AnswerSelectedListener {
public void onAnswerSelected(int position);
}
/**
* Listener interface for Practice mode toggle button, any Activity that attaches this Fragment must implement this.
*/
public interface PracticeModeToggleListener {
public void onPracticeModeToggle();
}
/**
* Build a fresh TableLayout for the given List of Strings.
* @param answerList The answers to display on the Buttons.
*/
public void initGrid(List<String> answerList) {
mAnswerList = answerList;
mFadedButtonList = new ArrayList<>();
clearGrid();
buildGrid();
}
/**
* Constructs a grid of Button objects from the mAnswerlist field.
*/
private void buildGrid() {
tl = new TableLayout(mCtx);
tl.setStretchAllColumns(true);
tl.setShrinkAllColumns(true);
base.addView(tl, new TableLayout.LayoutParams());
TableRow tr = null;
if(mAnswerList == null)
return;
for(int i = 0;i < mAnswerList.size(); i++) {
if(i % COLUMNS == 0) {
tr = new TableRow(mCtx);
tl.addView(tr);
}
Button b = new Button(mCtx);
b.setTextAppearance(mCtx , R.style.GridButtonStyle);
b.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.MATCH_PARENT));
b.setWidth(0);
b.setText(mAnswerList.get(i));
b.setId(i);
b.setOnClickListener(new GridButtonClickListener(i));
b.setBackground(getActivity().getResources().getDrawable(R.drawable.btn_default_holo_dark));
if (tr != null) {
tr.addView(b);
}
}
}
/**
* Clear the TableLayout.
*/
void clearGrid() {
if(tl != null)
tl.removeAllViews();
}
private static void answerSelected(int position) {
asListener.onAnswerSelected(position);
}
/**
* Fade out the Button at the given position.
* Fades out the given Button from 1.0 to 0.2 alpha in 500 ms, and stops
* the button from receiving further click events.
* @param position The position of the Button to fade out.
*/
public void fadeButton(int position) {
if(tl != null) {
Button b = (Button)tl.findViewById(position);
if(b != null) {
b.animate().setDuration(500).alpha((float) 0.5);
b.setClickable(false);
}
mFadedButtonList.add(position);
}
}
/**
* Undo any Alpha and setClickable changes done by fadeButton().
* Cancels any running animations on every Button to ensure the Alpha value isn't changed
* after this function..
*/
public void resetGridButtonState() {
int i = 0;
Button b;
if(tl != null) {
while((b = (Button)tl.findViewById(i)) != null) {
b.animate().cancel();
b.setAlpha(1.0f);
b.setClickable(true);
i++;
}
mFadedButtonList = new ArrayList<>();
}
}
/**
* Listener class for ButtonGridAdapter click events.
*
* @author Paul Klinkenberg <pklinken@gmail.com>
*/
public class GridButtonClickListener implements OnClickListener {
private final int position;
public GridButtonClickListener(int position) {
this.position = position;
}
@Override
public void onClick(View v) {
ButtonGridFragment.answerSelected(position);
}
}
}