package com.code44.finance.ui.common; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.os.Parcelable; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import com.code44.finance.R; import com.code44.finance.data.model.Model; import com.code44.finance.ui.DrawerActivity; import java.util.HashSet; import java.util.List; import java.util.Set; public abstract class ModelListActivity extends DrawerActivity implements LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener, View.OnClickListener { public static final String RESULT_EXTRA_MODEL = "RESULT_EXTRA_MODEL"; public static final String RESULT_EXTRA_MODELS = "RESULT_EXTRA_MODELS"; protected static final int LOADER_MODELS = 1245; private static final String EXTRA_MODE = ModelListActivity.class.getName() + ".EXTRA_MODE"; private static final String EXTRA_SELECTED_MODELS = ModelListActivity.class.getName() + ".EXTRA_SELECTED_MODELS"; protected Mode mode; protected Parcelable[] selectedModels; protected BaseModelsAdapter adapter; public static Intent makeViewIntent(Context context, Class<? extends ModelListActivity> activityClass) { final Intent intent = makeIntentForActivity(context, activityClass); intent.putExtra(EXTRA_MODE, Mode.VIEW); return intent; } public static Intent makeSelectIntent(Context context, Class<? extends ModelListActivity> activityClass) { final Intent intent = makeIntentForActivity(context, activityClass); intent.putExtra(EXTRA_MODE, Mode.SELECT); return intent; } public static Intent makeMultiSelectIntent(Context context, Class<? extends ModelListActivity> activityClass, List<? extends Model> selectedModels) { final Intent intent = makeIntentForActivity(context, activityClass); intent.putExtra(EXTRA_MODE, Mode.MULTI_SELECT); final Parcelable[] parcelables = new Parcelable[selectedModels.size()]; int index = 0; for (Model model : selectedModels) { parcelables[index++] = model; } intent.putExtra(EXTRA_SELECTED_MODELS, parcelables); return intent; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(getLayoutId()); onExtras(getIntent()); onViewCreated(); getSupportLoaderManager().initLoader(LOADER_MODELS, null, this); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.models, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_new: startModelEdit(null); return true; } return super.onOptionsItemSelected(item); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { if (id == LOADER_MODELS) { return getModelsCursorLoader(); } return null; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { if (loader.getId() == LOADER_MODELS) { adapter.swapCursor(data); } } @Override public void onLoaderReset(Loader<Cursor> loader) { if (loader.getId() == LOADER_MODELS) { adapter.swapCursor(null); } } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Model model = modelFrom(adapter.getCursor()); if (mode == Mode.VIEW) { onModelClick(view, position, model.getId(), model); } else if (mode == Mode.SELECT) { onModelSelected(model); } else { adapter.toggleModelSelected(modelFrom(adapter.getCursor())); } } @Override public void onClick(View view) { switch (view.getId()) { case R.id.saveButton: onMultipleModelsSelected(adapter.getSelectedModels()); break; case R.id.cancelButton: finish(); break; } } protected abstract int getLayoutId(); protected abstract BaseModelsAdapter createAdapter(); protected abstract CursorLoader getModelsCursorLoader(); protected abstract Model modelFrom(Cursor cursor); protected abstract void onModelClick(View view, int position, String modelId, Model model); protected abstract void startModelEdit(String modelId); protected void onExtras(Intent extras) { mode = (Mode) extras.getSerializableExtra(EXTRA_MODE); selectedModels = extras.getParcelableArrayExtra(EXTRA_SELECTED_MODELS); if (mode == null) { throw new IllegalStateException("Activity " + ((Object) this).getClass().getName() + " must be created with Intent containing " + EXTRA_MODE + " with values from " + Mode.class.getName()); } } protected void onViewCreated() { // Setup Toolbar if (mode != Mode.VIEW) { getSupportActionBar().setTitle(R.string.select); } // Get views final View editButtonsContainerView = findViewById(R.id.editButtonsContainerView); // Setup adapter = createAdapter(); if (mode == Mode.MULTI_SELECT) { final Set<Model> selectedModelsSet = new HashSet<>(); for (Parcelable parcelable : selectedModels) { selectedModelsSet.add((Model) parcelable); } adapter.setSelectedModels(selectedModelsSet); } if (editButtonsContainerView != null) { if (mode == Mode.MULTI_SELECT) { editButtonsContainerView.setVisibility(View.VISIBLE); final Button save_B = (Button) findViewById(R.id.saveButton); final Button cancel_B = (Button) findViewById(R.id.cancelButton); save_B.setOnClickListener(this); cancel_B.setOnClickListener(this); } else { editButtonsContainerView.setVisibility(View.GONE); } } onSetupList(adapter); } protected void onModelSelected(Model model) { final Intent data = new Intent(); data.putExtra(RESULT_EXTRA_MODEL, model); setResult(RESULT_OK, data); finish(); } protected void onMultipleModelsSelected(Set<Model> selectedModels) { final Intent data = new Intent(); final Parcelable[] parcelables = new Parcelable[selectedModels.size()]; int index = 0; for (Model model : selectedModels) { parcelables[index++] = model; } data.putExtra(RESULT_EXTRA_MODELS, parcelables); setResult(RESULT_OK, data); finish(); } protected Mode getMode() { return mode; } protected void onSetupList(BaseModelsAdapter adapter) { final ListView listView = (ListView) findViewById(R.id.listView); listView.setAdapter(adapter); listView.setOnItemClickListener(this); } public static enum Mode { VIEW, SELECT, MULTI_SELECT } }