package com.aberdyne.droidnavi; import java.util.Vector; import com.aberdyne.droidnavi.client.NonActiveServerConnection; import com.aberdyne.droidnavi.client.ServerConnection; import com.aberdyne.droidnavi.client.ServerListManager; import com.aberdyne.droidnavi.client.ServerListManager.ServerListListener; import com.aberdyne.droidnavi.zxing.IntentIntegrator; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ContextMenu.ContextMenuInfo; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; public class PairListFragment extends ListFragment { public PairListFragment() { super(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ServerListAdapter adapter = new ServerListAdapter(inflater.getContext(), android.R.layout.simple_list_item_1); this.setListAdapter(adapter); return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onActivityCreated(Bundle savedInstanceState) { registerForContextMenu(getListView()); // Enable the Context Menu for items super.onActivityCreated(savedInstanceState); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo; ListItem item = (ListItem)getListView().getItemAtPosition(info.position); /* Let the manager handle settings up the menus */ ContextMenuManager.onCreateContextMenu(item, menu, v, menuInfo); super.onCreateContextMenu(menu, v, menuInfo); } @Override public boolean onContextItemSelected(MenuItem item) { /* Let the manager handle commands */ ContextMenuManager.onContextItemSelected(item, getActivity()); return super.onContextItemSelected(item); } /** * Overloaded in order to catch single clicks on "Pairing" * A single click on "Pairing" will open the context menu for it. */ @Override public void onListItemClick(ListView l, View v, int position, long id) { ListItem item = (ListItem)this.getListView().getItemAtPosition(position); if(item == ListItem.PAIR_ITEM) { v.performLongClick(); } super.onListItemClick(l, v, position, id); } public class ServerListAdapter extends ArrayAdapter<ListItem> implements ServerListListener { private Vector<ListItem> items = new Vector<ListItem>(); public ServerListAdapter(Context context, int resource) { super(context, resource); items.add(ListItem.PAIR_ITEM); updateList(); ServerListManager.addServerListListener(this);; ServerListManager.getSync(context); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); ListItem item = items.get(position); TextView txtView = (TextView)view.findViewById(android.R.id.text1); if(item != ListItem.PAIR_ITEM) { int color = item.isConnected() ? view.getResources().getColor(android.R.color.holo_green_dark) : view.getResources().getColor(android.R.color.holo_red_dark); txtView.setTextColor(color); } else { txtView.setTextColor(view.getResources().getColor(android.R.color.primary_text_dark)); } return view; } public void onServerListChange(Action action, ServerConnection server) { ListItem newItem = ListItem.createItem(server); switch(action) { case SYNC: if(items.contains(newItem)) break; case ADD: if(items.contains(newItem)) break; else items.insertElementAt(newItem, 0); break; case REMOVE: items.remove(newItem); break; case UPDATE: // newItem IP = oldItem IP, but state is different now int position = items.indexOf(newItem); items.set(position, newItem); break; default: } updateList(); } private void updateList() { clear(); addAll(items); notifyDataSetChanged(); } } public static class ListItem { public static final ListItem PAIR_ITEM = new ListItem("Pair with new PC...", false); private String m_text = null; private boolean m_isConnected = false; private ListItem(String text, boolean isConnected) { m_text = text; m_isConnected = isConnected; } /** * Factory method for creating a ListItem * @param inet An InetAddress to add to the list * @return */ static public ListItem createItem(ServerConnection server) { if(server == null) { throw new NullPointerException("Create List Item: Inet was null."); } ListItem item = new ListItem(server.toString(), server.isConnected()); return item; } public boolean isConnected() { return m_isConnected; } @Override public String toString() { return m_text; } @Override public boolean equals(Object o) { if(o == null) { return false; } try { ListItem item = ListItem.class.cast(o); return this.toString().equals(item.toString()); } catch(ClassCastException e) { return false; } } } static private class ContextMenuManager { /** * An enum containing all the Context Menu items * @author Jeremy May * */ private enum MenuItems { MANUAL_INPUT("Manually input IP"), QRCODE("Pair using QR Code"), REMOVE("Remove pairing"); private String m_menuText = null; public String getMenuText() { return m_menuText; } /** * Retrieve a string array for the menu items that * should appear for Paired/Ip menu items. * @return A string array holding the text for each context menu item. */ static public MenuItems[] getIpMenuItems() { MenuItems[] list = { MenuItems.REMOVE }; return list; } /** * Retrieve the menu items that should appear with the "Pair with a Pc." * option. * @return A string array holding the text for each context menu item. */ static public MenuItems[] getPairingMenuItems() { MenuItems[] list = { MenuItems.MANUAL_INPUT, MenuItems.QRCODE }; return list; } static public MenuItems getItemById(int id) { MenuItems item = MenuItems.values()[id]; return item; } public int getItemId() { return this.ordinal(); } private MenuItems(String menuText) { m_menuText = menuText; } } /** * The actual handler for item selection * @param item The MenuItem selected * @param parent The context for the activity * @param callback An object implementing the ListEditable methods. * @return */ static public boolean onContextItemSelected(MenuItem item, Context parent) { int itemId = item.getItemId(); MenuItems selected = MenuItems.getItemById(itemId); switch(selected) { case MANUAL_INPUT: IpInputDialog.showDialog(parent); break; case QRCODE: IntentIntegrator integrator = new IntentIntegrator((Activity)parent); integrator.initiateScan(); break; case REMOVE: AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); String ip = ((TextView)info.targetView).getText().toString(); ServerConnection server = new NonActiveServerConnection(ip); ServerListManager.removeServer(parent, server); break; } return false; } /** * The actual handler for the List's Context Menu creation * @param item The ListItem that triggered the Context Menu * @param menu See android doc. * @param v See android doc. * @param menuInfo See android doc. */ static public void onCreateContextMenu(ListItem item, ContextMenu menu, View v, ContextMenuInfo menuInfo) { MenuItems[] menuItems = null; if(item == ListItem.PAIR_ITEM) { menuItems = MenuItems.getPairingMenuItems(); } else { menuItems = MenuItems.getIpMenuItems(); } for(int i = 0; i < menuItems.length; i++) { menu.add(Menu.NONE, menuItems[i].getItemId(), i, menuItems[i].getMenuText()); } } } }