/* * Apple // emulator for *nix * * This software package is subject to the GNU General Public License * version 3 or later (your choice) as published by the Free Software * Foundation. * * Copyright 2015 Aaron Culliney * */ package org.deadc0de.apple2ix; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CheckedTextView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.SeekBar; import android.widget.TextView; import org.deadc0de.apple2ix.basic.R; public abstract class Apple2AbstractMenu implements Apple2MenuView { private final static String TAG = "Apple2AbstractMenu"; protected Apple2Activity mActivity = null; private View mSettingsView = null; public Apple2AbstractMenu(Apple2Activity activity) { mActivity = activity; setup(); } public synchronized void show() { if (isShowing()) { return; } mActivity.pushApple2View(this); } public void dismiss() { mActivity.popApple2View(this); } public void dismissAll() { this.dismiss(); } public boolean isShowing() { return mSettingsView.isShown(); } public View getView() { return mSettingsView; } public boolean isCalibrating() { return false; } public void onKeyTapCalibrationEvent(char ascii, int scancode) { /* ... */ } // ------------------------------------------------------------------------ // required overrides ... public interface IMenuEnum { public String getTitle(final Apple2Activity activity); public String getSummary(final Apple2Activity activity); public View getView(final Apple2Activity activity, View convertView); public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked); } public abstract IMenuEnum[] allValues(); public abstract String[] allTitles(); public abstract boolean areAllItemsEnabled(); public abstract boolean isEnabled(int position); // ------------------------------------------------------------------------ // boilerplate menu view code protected static View _basicView(Apple2Activity activity, IMenuEnum setting, View convertView) { TextView tv = (TextView) convertView.findViewById(R.id.a2preference_title); if (tv == null) { // attemping to recycle different layout ... LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.a2preference, null, false); tv = (TextView) convertView.findViewById(R.id.a2preference_title); } tv.setText(setting.getTitle(activity)); tv = (TextView) convertView.findViewById(R.id.a2preference_summary); tv.setText(setting.getSummary(activity)); LinearLayout layout = (LinearLayout) convertView.findViewById(R.id.a2preference_widget_frame); if (layout.getChildCount() > 0) { // layout cells appear to be reused when scrolling into view ... make sure we start with clear hierarchy layout.removeAllViews(); } return convertView; } public interface IPreferenceLoadSave { public int intValue(); public void saveInt(int value); } public interface IPreferenceSlider extends IPreferenceLoadSave { public void showValue(int value, final TextView seekBarValue); } protected static View _sliderView(final Apple2Activity activity, final IMenuEnum setting, final int numChoices, final IPreferenceSlider iLoadSave) { LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.a2preference_slider, null, false); TextView tv = (TextView) view.findViewById(R.id.a2preference_slider_summary); tv.setText(setting.getSummary(activity)); final TextView seekBarValue = (TextView) view.findViewById(R.id.a2preference_slider_seekBarValue); SeekBar sb = (SeekBar) view.findViewById(R.id.a2preference_slider_seekBar); sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (!fromUser) { return; } iLoadSave.showValue(progress, seekBarValue); iLoadSave.saveInt(progress); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); sb.setMax(0); // http://stackoverflow.com/questions/10278467/seekbar-not-setting-actual-progress-setprogress-not-working-on-early-android sb.setMax(numChoices); int progress = iLoadSave.intValue(); sb.setProgress(progress); iLoadSave.showValue(progress, seekBarValue); return view; } protected static void _alertDialogHandleSelection(final Apple2Activity activity, final int titleId, final String[] choices, final IPreferenceLoadSave iLoadSave) { _alertDialogHandleSelection(activity, activity.getResources().getString(titleId), choices, iLoadSave); } protected static void _alertDialogHandleSelection(final Apple2Activity activity, final String titleId, final String[] choices, final IPreferenceLoadSave iLoadSave) { AlertDialog.Builder builder = new AlertDialog.Builder(activity).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(titleId); builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); final int checkedPosition = iLoadSave.intValue(); final ArrayAdapter adapter = new ArrayAdapter(activity, android.R.layout.select_dialog_singlechoice, choices) { @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); CheckedTextView ctv = (CheckedTextView) view.findViewById(android.R.id.text1); ctv.setChecked(position == checkedPosition); return view; } }; builder.setAdapter(adapter, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int value) { iLoadSave.saveInt(value); dialog.dismiss(); } }); AlertDialog dialog = builder.create(); activity.registerAndShowDialog(dialog); } protected static ImageView _addPopupIcon(Apple2Activity activity, IMenuEnum setting, View convertView) { ImageView imageView = new ImageView(activity); Drawable drawable = activity.getResources().getDrawable(android.R.drawable.ic_menu_edit); imageView.setImageDrawable(drawable); LinearLayout layout = (LinearLayout) convertView.findViewById(R.id.a2preference_widget_frame); layout.addView(imageView); return imageView; } protected static CheckBox _addCheckbox(Apple2Activity activity, IMenuEnum setting, View convertView, boolean isChecked) { CheckBox checkBox = new CheckBox(activity); checkBox.setChecked(isChecked); LinearLayout layout = (LinearLayout) convertView.findViewById(R.id.a2preference_widget_frame); layout.addView(checkBox); return checkBox; } private void setup() { LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mSettingsView = inflater.inflate(R.layout.activity_settings, null, false); final Button cancelButton = (Button) mSettingsView.findViewById(R.id.cancelButton); cancelButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mActivity.dismissAllMenus(); } }); ListView settingsList = (ListView) mSettingsView.findViewById(R.id.listView_settings); settingsList.setEnabled(true); ArrayAdapter adapter = new ArrayAdapter(mActivity, R.layout.a2preference, R.id.a2preference_title, allTitles()) { @Override public boolean areAllItemsEnabled() { return Apple2AbstractMenu.this.areAllItemsEnabled(); } @Override public boolean isEnabled(int position) { return Apple2AbstractMenu.this.isEnabled(position); } @Override public View getView(int position, View convertView, ViewGroup parent) { //View view = super.getView(position, convertView, parent); // ^^^ WHOA ... this is catching an NPE deep in AOSP code on the second time loading ... WTF? // Methinks it is related to the hack of loading a completely different R.layout.something for certain views... View view = convertView != null ? convertView : super.getView(position, null, parent); IMenuEnum setting = allValues()[position]; return setting.getView(mActivity, view); } }; settingsList.setAdapter(adapter); settingsList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { IMenuEnum setting = allValues()[position]; LinearLayout layout = (LinearLayout) view.findViewById(R.id.a2preference_widget_frame); if (layout == null) { return; } View childView = layout.getChildAt(0); boolean selected = false; if (childView != null && childView instanceof CheckBox) { CheckBox checkBox = (CheckBox) childView; checkBox.setChecked(!checkBox.isChecked()); selected = checkBox.isChecked(); } setting.handleSelection(mActivity, Apple2AbstractMenu.this, selected); } }); } }