/* * Copyright (C) 2009 Android Shuffle Open Source Project * * 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 org.dodgybits.shuffle.android.list.activity; import org.dodgybits.android.shuffle.R; import org.dodgybits.shuffle.android.core.activity.flurry.FlurryEnabledListActivity; import org.dodgybits.shuffle.android.core.model.Entity; import org.dodgybits.shuffle.android.core.model.Id; import org.dodgybits.shuffle.android.core.view.MenuUtils; import org.dodgybits.shuffle.android.list.config.ListConfig; import org.dodgybits.shuffle.android.preference.model.Preferences; import android.app.Activity; import android.content.ContentUris; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.ContextMenu; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ContextMenu.ContextMenuInfo; import android.widget.AdapterView; import android.widget.CursorAdapter; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.Toast; public abstract class AbstractListActivity<T extends Entity> extends FlurryEnabledListActivity { public static final String cSelectedItem = "SELECTED_ITEM"; private static final String cTag = "AbstractListActivity"; protected final int NEW_ITEM = 1; // after a new item is added, select it private Long mItemIdToSelect = null; private ListConfig<T> mConfig; /** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); mConfig = createListConfig(); setContentView(getListConfig().getContentViewResId()); setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT); // If no data was given in the intent (because we were started // as a MAIN activity), then use our default content provider. Intent intent = getIntent(); if (intent.getData() == null) { intent.setData(getListConfig().getPersister().getContentUri()); } // Inform the view we provide context menus for items getListView().setOnCreateContextMenuListener(this); Cursor cursor = getListConfig().createQuery(this); setListAdapter(createListAdapter(cursor)); } @Override protected void onResume() { super.onResume(); setTitle(getListConfig().createTitle(this)); // attempt to select newly created item (if any) if (mItemIdToSelect != null) { Log.d(cTag, "New item id = " + mItemIdToSelect); // see if list contains the new item int count = getItemCount(); CursorAdapter adapter = (CursorAdapter) getListAdapter(); for (int i = 0; i < count; i++) { long currentItemId = adapter.getItemId(i); Log.d(cTag, "Current id=" + currentItemId + " pos=" + i); if (currentItemId == mItemIdToSelect) { Log.d(cTag, "Found new item - selecting"); setSelection(i); break; } } mItemIdToSelect = null; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { Log.d(cTag, "Got resultCode " + resultCode + " with data " + data); switch (requestCode) { case NEW_ITEM: if (resultCode == Activity.RESULT_OK) { if (data != null) { String selectedItem = data.getStringExtra(cSelectedItem); if (selectedItem != null) { Uri uri = Uri.parse(selectedItem); mItemIdToSelect = ContentUris.parseId(uri); // need to do the actual checking and selecting // in onResume, otherwise getItemId(i) is always 0 // and setSelection(i) does nothing } } } break; default: Log.e(cTag, "Unknown requestCode: " + requestCode); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_N: // go to previous view int prevView = getListConfig().getCurrentViewMenuId() - 1; if (prevView < MenuUtils.INBOX_ID) { prevView = MenuUtils.CONTEXT_ID; } MenuUtils.checkCommonItemsSelected(prevView, this, getListConfig().getCurrentViewMenuId()); return true; case KeyEvent.KEYCODE_M: // go to previous view int nextView = getListConfig().getCurrentViewMenuId() + 1; if (nextView > MenuUtils.CONTEXT_ID) { nextView = MenuUtils.INBOX_ID; } MenuUtils.checkCommonItemsSelected(nextView, this, getListConfig().getCurrentViewMenuId()); return true; } return super.onKeyDown(keyCode, event); } @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuItem item = menu.findItem(MenuUtils.SYNC_ID); if (item != null) { item.setVisible(Preferences.validateTracksSettings(this)); } return true; } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuUtils.addInsertMenuItems(menu, getListConfig().getItemName(this), getListConfig().isTaskList(), this); MenuUtils.addViewMenuItems(menu, getListConfig().getCurrentViewMenuId()); MenuUtils.addPrefsHelpMenuItems(this, menu); MenuUtils.addSearchMenuItem(this, menu); return true; } @Override public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { AdapterView.AdapterContextMenuInfo info; try { info = (AdapterView.AdapterContextMenuInfo) menuInfo; } catch (ClassCastException e) { Log.e(cTag, "bad menuInfo", e); return; } Cursor cursor = (Cursor) getListAdapter().getItem(info.position); if (cursor == null) { // For some reason the requested item isn't available, do nothing return; } // Setup the menu header menu.setHeaderTitle(cursor.getString(1)); Uri selectedUri = ContentUris.withAppendedId(getListConfig().getPersister().getContentUri(), info.id); MenuUtils.addSelectedAlternativeMenuItems(menu, selectedUri, false); // ... and ends with the delete command. MenuUtils.addDeleteMenuItem(menu); } @Override public boolean onContextItemSelected(MenuItem item) { AdapterView.AdapterContextMenuInfo info; try { info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); } catch (ClassCastException e) { Log.e(cTag, "bad menuInfo", e); return false; } switch (item.getItemId()) { case MenuUtils.DELETE_ID: { // Delete the item that the context menu is for deleteItem(Id.create(info.id)); return true; } } return false; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MenuUtils.INSERT_ID: // Launch activity to insert a new item startActivityForResult(getInsertIntent(), NEW_ITEM); return true; } if (MenuUtils.checkCommonItemsSelected(item, this, getListConfig().getCurrentViewMenuId())) { return true; } return super.onOptionsItemSelected(item); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { Uri url = ContentUris.withAppendedId(getListConfig().getPersister().getContentUri(), id); String action = getIntent().getAction(); if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)) { // The caller is waiting for us to return a task selected by // the user. They have clicked on one, so return it now. Bundle bundle = new Bundle(); bundle.putString(cSelectedItem, url.toString()); Intent mIntent = new Intent(); mIntent.putExtras(bundle); setResult(RESULT_OK, mIntent); } else { // Launch activity to view/edit the currently selected item startActivity(getClickIntent(url)); } } abstract protected ListConfig<T> createListConfig(); abstract protected ListAdapter createListAdapter(Cursor cursor); // custom helper methods protected final ListConfig<T> getListConfig() { return mConfig; } /** * Permanently delete the given list item. */ protected void deleteItem(Id id) { getListConfig().getPersister().moveToTrash(id); String text = getResources().getString( R.string.itemDeletedToast, getListConfig().getItemName(this)); Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); } /** * @return Number of items in the list. */ protected final int getItemCount() { return getListAdapter().getCount(); } /** * The intent to insert a new item in this list. Default to an insert action * on the list type which is all you need most of the time. */ protected Intent getInsertIntent() { return new Intent(Intent.ACTION_INSERT, getListConfig().getPersister().getContentUri()); } /** * Return the intent generated when a list item is clicked. * * @param url * type of data selected */ protected Intent getClickIntent(Uri uri) { return new Intent(Intent.ACTION_EDIT, uri); } }