# HG changeset patch # User Medo # Date 1342995426 -7200 # Node ID 641f11cdd319808abddd1a5fb900fb34fdc03813 # Parent 12fdfd2038d4613a7bcd7372d8c391ac05325038 Hedgeroid: Reworked player and room lists, added menus, added playername query Still work in progress... diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/AndroidManifest.xml --- a/project_files/Android-build/SDL-android-project/AndroidManifest.xml Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/AndroidManifest.xml Mon Jul 23 00:17:06 2012 +0200 @@ -69,7 +69,10 @@ + android:label="@string/title_activity_lobby" + android:screenOrientation="landscape" + + android:windowSoftInputMode="adjustResize" > \ No newline at end of file diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/res/layout-large/listview_room.xml --- a/project_files/Android-build/SDL-android-project/res/layout-large/listview_room.xml Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/res/layout-large/listview_room.xml Mon Jul 23 00:17:06 2012 +0200 @@ -3,7 +3,8 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:minHeight="20dp" > + android:paddingTop="4dp" + android:paddingBottom="4dp"> + android:mode="twoLine" + android:paddingTop="4dp" + android:paddingBottom="4dp"> + + \ No newline at end of file diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/res/menu/lobby_playerlist_context.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/res/menu/lobby_playerlist_context.xml Mon Jul 23 00:17:06 2012 +0200 @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/res/menu/lobby_roomlist_options.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/res/menu/lobby_roomlist_options.xml Mon Jul 23 00:17:06 2012 +0200 @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/res/values/strings.xml --- a/project_files/Android-build/SDL-android-project/res/values/strings.xml Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/res/values/strings.xml Mon Jul 23 00:17:06 2012 +0200 @@ -73,7 +73,7 @@ Owner Map Rules - Ammo + Weapons by %1$s Map: %1$s @@ -86,4 +86,16 @@ %1$s has joined. %1$s has left. %1$s has left (%2$s). + + + Connect + Please select a username. + Enter a username here + + Info (shown in chat) + Follow + Create room + Refresh + + Sorry, not implemented yet. :( diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java Mon Jul 23 00:17:06 2012 +0200 @@ -31,14 +31,23 @@ import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.support.v4.app.FragmentActivity; +import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; +import android.widget.EditText; import android.widget.Toast; public class MainActivity extends FragmentActivity { + private static final int DIALOG_NO_SDCARD = 0; + private static final int DIALOG_START_NETGAME = 1; + + private static final String PREF_PLAYERNAME = "playerName"; + private Button downloader, startGame; private ProgressDialog assetsDialog; @@ -54,12 +63,12 @@ startGame.setOnClickListener(startGameClicker); joinLobby.setOnClickListener(new OnClickListener() { public void onClick(View v) { - startActivity(new Intent(getApplicationContext(), LobbyActivity.class)); + showDialog(DIALOG_START_NETGAME); } }); if(!Utils.isDataPathAvailable()){ - showDialog(0); + showDialog(DIALOG_NO_SDCARD); } else { String existingVersion = ""; try { @@ -83,6 +92,17 @@ } public Dialog onCreateDialog(int id, Bundle args){ + switch(id) { + case DIALOG_NO_SDCARD: + return createNoSdcardDialog(); + case DIALOG_START_NETGAME: + return createStartNetgameDialog(); + default: + throw new IndexOutOfBoundsException(); + } + } + + private Dialog createNoSdcardDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.sdcard_not_mounted_title); builder.setMessage(R.string.sdcard_not_mounted); @@ -95,6 +115,43 @@ return builder.create(); } + private Dialog createStartNetgameDialog() { + final SharedPreferences prefs = getPreferences(MODE_PRIVATE); + final String playerName = prefs.getString(PREF_PLAYERNAME, "Player"); + final EditText editText = new EditText(this); + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + + editText.setText(playerName); + editText.setHint(R.string.start_netgame_dialog_playername_hint); + editText.setId(android.R.id.text1); + + builder.setTitle(R.string.start_netgame_dialog_title); + builder.setMessage(R.string.start_netgame_dialog_message); + builder.setView(editText); + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + editText.setText(playerName); + } + }); + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + String playerName = editText.getText().toString(); + if(playerName.length() > 0) { + Editor edit = prefs.edit(); + edit.putString(PREF_PLAYERNAME, playerName); + edit.commit(); + + // TODO actually use that name + Intent netplayIntent = new Intent(getApplicationContext(), LobbyActivity.class); + netplayIntent.putExtra("playerName", playerName); + startActivity(netplayIntent); + } + } + }); + + return builder.create(); + } + public void onAssetsDownloaded(boolean result){ if(!result){ Toast.makeText(this, R.string.download_failed, Toast.LENGTH_LONG).show(); diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyChatFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyChatFragment.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyChatFragment.java Mon Jul 23 00:17:06 2012 +0200 @@ -85,13 +85,13 @@ public void onServiceConnected(ComponentName className, IBinder binder) { Log.d("LobbyChatFragment", "netconn received"); netconn = ((NetplayBinder) binder).getNetconn(); - adapter.setLog(netconn.lobbyLog.getLog()); - netconn.lobbyLog.registerObserver(adapter); + adapter.setLog(netconn.lobbyChatlog.getLog()); + netconn.lobbyChatlog.registerObserver(adapter); } public void onServiceDisconnected(ComponentName className) { // TODO navigate away - netconn.lobbyLog.unregisterObserver(adapter); + netconn.lobbyChatlog.unregisterObserver(adapter); netconn = null; } }; diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java Mon Jul 23 00:17:06 2012 +0200 @@ -27,6 +27,7 @@ private static final int BACKLOG_LINES = 200; private static final int INFO_COLOR = Color.GRAY; + private static final int PLAYERINFO_COLOR = Color.GREEN; private static final int CHAT_COLOR = Color.GREEN; private static final int MECHAT_COLOR = Color.CYAN; private static final int WARN_COLOR = Color.RED; @@ -111,8 +112,8 @@ append(withColor("***"+msg, WARN_COLOR)); break; case JnaFrontlib.NETCONN_MSG_TYPE_PLAYERINFO: - // TODO better formatting or different way to display - append(msg); + // TODO Display in popup? + append(withColor(msg.replace("\n", " "), PLAYERINFO_COLOR)); break; case JnaFrontlib.NETCONN_MSG_TYPE_SERVERMESSAGE: appendRaw(span(TextUtils.concat("\n", Html.fromHtml(msg), "\n"), new RelativeSizeSpan(1.5f))); diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netconn.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netconn.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netconn.java Mon Jul 23 00:17:06 2012 +0200 @@ -33,23 +33,24 @@ private NetconnPtr conn; private String playerName; + private boolean joined; // True once we have been admitted to the lobby public final PlayerList playerList = new PlayerList(); public final RoomList roomList = new RoomList(); - public final MessageLog lobbyLog; - public final MessageLog roomLog; + public final MessageLog lobbyChatlog; + public final MessageLog roomChatlog; private StrCallback lobbyJoinCb = new StrCallback() { public void callback(Pointer context, String arg1) { playerList.addPlayerWithNewId(arg1); - lobbyLog.appendPlayerJoin(arg1); + lobbyChatlog.appendPlayerJoin(arg1); } }; private StrStrCallback lobbyLeaveCb = new StrStrCallback() { public void callback(Pointer context, String name, String msg) { - playerList.remove(name); - lobbyLog.appendPlayerLeave(name, msg); + playerList.removePlayer(name); + lobbyChatlog.appendPlayerLeave(name, msg); } }; @@ -79,23 +80,21 @@ private StrCallback roomDeleteCb = new StrCallback() { public void callback(Pointer context, String name) { - roomList.remove(name); + roomList.removeRoom(name); } }; private VoidCallback connectedCb = new VoidCallback() { public void callback(Pointer context) { // TODO I guess more needs to happen here... + joined = true; FLIB.flib_netconn_send_request_roomlist(conn); } }; private RoomListCallback roomlistCb = new RoomListCallback() { public void callback(Pointer context, RoomArrayPtr arg1, int count) { - roomList.clear(); - for(RoomPtr roomPtr : arg1.getRooms(count)) { - roomList.addRoomWithNewId(roomPtr); - } + roomList.updateList(arg1.getRooms(count)); } }; @@ -125,8 +124,8 @@ playerName = "Player"; } this.playerName = playerName; - this.lobbyLog = new MessageLog(context); - this.roomLog = new MessageLog(context); + this.lobbyChatlog = new MessageLog(context); + this.roomChatlog = new MessageLog(context); MetaschemePtr meta = null; File dataPath = Utils.getDataPathFile(context); @@ -170,24 +169,25 @@ public void sendChat(String s) { FLIB.flib_netconn_send_chat(conn, s); if(FLIB.flib_netconn_is_in_room_context(conn)) { - roomLog.appendChat(playerName, s); + roomChatlog.appendChat(playerName, s); } else { - lobbyLog.appendChat(playerName, s); + lobbyChatlog.appendChat(playerName, s); } } private MessageLog getCurrentLog() { if(FLIB.flib_netconn_is_in_room_context(conn)) { - return roomLog; + return roomChatlog; } else { - return lobbyLog; + return lobbyChatlog; } } public void sendNick(String nick) { FLIB.flib_netconn_send_nick(conn, nick); } public void sendPassword(String password) { FLIB.flib_netconn_send_password(conn, password); } public void sendQuit(String message) { FLIB.flib_netconn_send_quit(conn, message); } - public void sendRoomlistRequest() { FLIB.flib_netconn_send_request_roomlist(conn); } + public void sendRoomlistRequest() { if(joined) FLIB.flib_netconn_send_request_roomlist(conn); } + public void sendPlayerInfoQuery(String name) { FLIB.flib_netconn_send_playerInfo(conn, name); } public boolean isConnected() { return conn != null; @@ -200,4 +200,5 @@ Log.e("Netconn", "Leaked Netconn object"); } } + } \ No newline at end of file diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ObservableLinkedHashMap.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ObservableLinkedHashMap.java Sat Jul 21 14:56:52 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -package org.hedgewars.hedgeroid.netplay; - -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * A map of items, sorted by time of insertion (earliest first). - * Observers can be notified about insertions, deletions and changes (which don't change the order). - * This is useful for e.g. the lists of current rooms and players, because it allows easy addition - * and removal of entries on the one side, as well as reaction to these events by UI elements. - */ -public class ObservableLinkedHashMap { - private LinkedHashMap map = new LinkedHashMap(); - private List> observers = new LinkedList>(); - - public Collection getValues() { - return Collections.unmodifiableCollection(map.values()); - } - - public Map getMap() { - return Collections.unmodifiableMap(map); - } - - public void observe(Observer observer) { - observers.add(observer); - } - - public void unobserve(Observer observer) { - observers.remove(observer); - } - - // TODO ugh - public void clear() { - while(!map.isEmpty()) { - remove(map.keySet().iterator().next()); - } - } - - public void put(K key, V value) { - V oldValue = map.put(key, value); - Map unmodifiableMap = Collections.unmodifiableMap(map); - if(oldValue != null) { - for(Observer o : observers) { - o.itemReplaced(unmodifiableMap, key, oldValue, value); - } - } else { - for(Observer o : observers) { - o.itemAdded(unmodifiableMap, key, value); - } - } - } - - public void remove(K key) { - V oldValue = map.remove(key); - if(oldValue != null) { - Map unmodifiableMap = Collections.unmodifiableMap(map); - for(Observer o : observers) { - o.itemRemoved(unmodifiableMap, key, oldValue); - } - } - } - - public static interface Observer { - void itemAdded(Map map, K key, V value); - void itemRemoved(Map map, K key, V oldValue); - void itemReplaced(Map map, K key, V oldValue, V newValue); - } -} diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Player.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Player.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Player.java Mon Jul 23 00:17:06 2012 +0200 @@ -3,7 +3,7 @@ import java.util.Comparator; public class Player { - public static final ByNameComparator nameComparator = new ByNameComparator(); + public static final ByNameComparator NAME_COMPARATOR = new ByNameComparator(); public final String name; public final long id; // for ListView @@ -13,7 +13,7 @@ this.id = id; } - private static class ByNameComparator implements Comparator { + private static final class ByNameComparator implements Comparator { public int compare(Player lhs, Player rhs) { return lhs.name.compareToIgnoreCase(rhs.name); } diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerList.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerList.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerList.java Mon Jul 23 00:17:06 2012 +0200 @@ -1,12 +1,28 @@ package org.hedgewars.hedgeroid.netplay; -public class PlayerList extends ObservableLinkedHashMap { +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +import android.database.DataSetObservable; + +public class PlayerList extends DataSetObservable { private long nextId = 1; + private Map players = new TreeMap(); public void addPlayerWithNewId(String name) { Player p = new Player(name, nextId++); - put(name, p); + players.put(name, p); + notifyChanged(); } - public interface Observer extends ObservableLinkedHashMap.Observer {} + public void removePlayer(String name) { + if(players.remove(name) != null) { + notifyChanged(); + } + } + + public Map getMap() { + return Collections.unmodifiableMap(players); + } } diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerListAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerListAdapter.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerListAdapter.java Mon Jul 23 00:17:06 2012 +0200 @@ -1,24 +1,35 @@ package org.hedgewars.hedgeroid.netplay; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Map; import org.hedgewars.hedgeroid.R; -import org.hedgewars.hedgeroid.netplay.PlayerList.Observer; import android.content.Context; +import android.database.DataSetObserver; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; -public class PlayerListAdapter extends BaseAdapter implements Observer { +public class PlayerListAdapter extends BaseAdapter { private List players = new ArrayList(); private Context context; + private PlayerList playerList; + + private DataSetObserver observer = new DataSetObserver() { + @Override + public void onChanged() { + reloadFromList(playerList); + } + + @Override + public void onInvalidated() { + invalidate(); + } + }; public PlayerListAdapter(Context context) { this.context = context; @@ -28,7 +39,7 @@ return players.size(); } - public Object getItem(int position) { + public Player getItem(int position) { return players.get(position); } @@ -39,23 +50,28 @@ public boolean hasStableIds() { return true; } - - public void itemAdded(Map map, String key, Player value) { - setPlayerList(map.values()); - } - - public void itemRemoved(Map map, String key, Player oldValue) { - setPlayerList(map.values()); - } - - public void itemReplaced(Map map, String key, - Player oldValue, Player newValue) { - setPlayerList(map.values()); + + public void setList(PlayerList playerList) { + if(this.playerList != null) { + this.playerList.unregisterObserver(observer); + } + this.playerList = playerList; + this.playerList.registerObserver(observer); + reloadFromList(playerList); } - public void setPlayerList(Collection players) { - this.players = new ArrayList(players); - Collections.sort(this.players, Player.nameComparator); + public void invalidate() { + players = new ArrayList(); + if(playerList != null) { + playerList.unregisterObserver(observer); + } + playerList = null; + notifyDataSetInvalidated(); + } + + private void reloadFromList(PlayerList list) { + players = new ArrayList(list.getMap().values()); + Collections.sort(players, Player.NAME_COMPARATOR); notifyDataSetChanged(); } diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerlistFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerlistFragment.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerlistFragment.java Mon Jul 23 00:17:06 2012 +0200 @@ -10,9 +10,15 @@ import android.os.Bundle; import android.os.IBinder; import android.support.v4.app.ListFragment; +import android.view.ContextMenu; import android.view.LayoutInflater; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.view.ContextMenu.ContextMenuInfo; +import android.widget.Toast; +import android.widget.AdapterView.AdapterContextMenuInfo; public class PlayerlistFragment extends ListFragment { private Netconn netconn; @@ -28,6 +34,38 @@ } @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + registerForContextMenu(getListView()); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + MenuInflater inflater = getActivity().getMenuInflater(); + inflater.inflate(R.menu.lobby_playerlist_context, menu); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo(); + switch(item.getItemId()) { + case R.id.player_info: + Player p = playerListAdapter.getItem(info.position); + if(netconn != null) { + netconn.sendPlayerInfoQuery(p.name); + } + return true; + case R.id.player_follow: + Toast.makeText(getActivity(), R.string.not_implemented_yet, Toast.LENGTH_SHORT).show(); + return true; + default: + return super.onContextItemSelected(item); + } + } + + @Override public void onDestroy() { super.onDestroy(); getActivity().unbindService(serviceConnection); @@ -42,13 +80,12 @@ private ServiceConnection serviceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder binder) { netconn = ((NetplayBinder) binder).getNetconn(); - playerListAdapter.setPlayerList(netconn.playerList.getValues()); - netconn.playerList.observe(playerListAdapter); + playerListAdapter.setList(netconn.playerList); } public void onServiceDisconnected(ComponentName className) { // TODO navigate away - netconn.playerList.unobserve(playerListAdapter); + playerListAdapter.invalidate(); netconn = null; } }; diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Room.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Room.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Room.java Mon Jul 23 00:17:06 2012 +0200 @@ -1,5 +1,7 @@ package org.hedgewars.hedgeroid.netplay; +import java.util.Comparator; + import org.hedgewars.hedgeroid.R; import android.content.res.Resources; @@ -8,6 +10,7 @@ public static final String MAP_REGULAR = "+rnd+"; public static final String MAP_MAZE = "+maze+"; public static final String MAP_DRAWN = "+drawn+"; + public static final Comparator ID_COMPARATOR = new ByIdComparator(); public final String name, map, scheme, weapons, owner; public final int playerCount, teamCount; @@ -39,4 +42,10 @@ } return map; } + + private static final class ByIdComparator implements Comparator { + public int compare(Room lhs, Room rhs) { + return lhs.idrhs.id ? 1 : 0; + } + } } diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomList.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomList.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomList.java Mon Jul 23 00:17:06 2012 +0200 @@ -1,34 +1,68 @@ package org.hedgewars.hedgeroid.netplay; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + import org.hedgewars.hedgeroid.netplay.JnaFrontlib.RoomPtr; +import android.database.DataSetObservable; import android.util.Log; -public class RoomList extends ObservableLinkedHashMap { +public class RoomList extends DataSetObservable { private long nextId = 1; + private Map rooms = new TreeMap(); + + public void updateList(RoomPtr[] roomPtrs) { + Map newMap = new TreeMap(); + for(RoomPtr roomPtr : roomPtrs) { + JnaFrontlib.Room room = roomPtr.deref(); + Room oldEntry = rooms.get(room.name); + if(oldEntry == null) { + newMap.put(room.name, buildRoom(room, nextId++)); + } else { + newMap.put(room.name, buildRoom(room, oldEntry.id)); + } + } + rooms = newMap; + notifyChanged(); + } public void addRoomWithNewId(RoomPtr roomPtr) { - JnaFrontlib.Room r = roomPtr.deref(); - long id = nextId++; - put(r.name, new Room(r.name, r.map, r.scheme, r.weapons, r.owner, r.playerCount, r.teamCount, r.inProgress, id)); + putRoom(roomPtr.deref(), nextId++); + notifyChanged(); } public void updateRoom(String name, RoomPtr roomPtr) { - Room oldEntry = getMap().get(name); + JnaFrontlib.Room room = roomPtr.deref(); + Room oldEntry = rooms.get(name); if(oldEntry == null) { Log.e("RoomList", "Received update for unknown room: "+name); + putRoom(room, nextId++); } else { - JnaFrontlib.Room r = roomPtr.deref(); - /* - * TODO Room renames are handled as re-insertions which push the room - * up to the top of the list again. Should maybe be revisited (sorting by ID is an option) - */ - if(!r.name.equals(oldEntry.name)) { - remove(oldEntry.name); + if(!name.equals(room.name)) { + rooms.remove(name); } - put(r.name, new Room(r.name, r.map, r.scheme, r.weapons, r.owner, r.playerCount, r.teamCount, r.inProgress, oldEntry.id)); + putRoom(room, oldEntry.id); + } + notifyChanged(); + } + + public void removeRoom(String name) { + if(rooms.remove(name) != null) { + notifyChanged(); } } - - public static interface Observer extends ObservableLinkedHashMap.Observer { } + + public Map getMap() { + return Collections.unmodifiableMap(rooms); + } + + private void putRoom(JnaFrontlib.Room r, long id) { + rooms.put(r.name, buildRoom(r, id)); + } + + private Room buildRoom(JnaFrontlib.Room r, long id) { + return new Room(r.name, r.map, r.scheme, r.weapons, r.owner, r.playerCount, r.teamCount, r.inProgress, id); + } } diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomListAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomListAdapter.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomListAdapter.java Mon Jul 23 00:17:06 2012 +0200 @@ -1,25 +1,36 @@ package org.hedgewars.hedgeroid.netplay; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Map; import org.hedgewars.hedgeroid.R; -import org.hedgewars.hedgeroid.netplay.RoomList.Observer; import android.content.Context; import android.content.res.Resources; +import android.database.DataSetObserver; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; -public class RoomListAdapter extends BaseAdapter implements Observer { +public class RoomListAdapter extends BaseAdapter { private List rooms = new ArrayList(); private Context context; + private RoomList roomList; + + private DataSetObserver observer = new DataSetObserver() { + @Override + public void onChanged() { + reloadFromList(roomList); + } + + @Override + public void onInvalidated() { + invalidate(); + } + }; public RoomListAdapter(Context context) { this.context = context; @@ -29,7 +40,7 @@ return rooms.size(); } - public Object getItem(int position) { + public Room getItem(int position) { return rooms.get(position); } @@ -41,9 +52,27 @@ return true; } - public void setList(Collection rooms) { - this.rooms = new ArrayList(rooms); - Collections.reverse(this.rooms); // We want to show the newest rooms first + public void setList(RoomList roomList) { + if(this.roomList != null) { + this.roomList.unregisterObserver(observer); + } + this.roomList = roomList; + this.roomList.registerObserver(observer); + reloadFromList(roomList); + } + + public void invalidate() { + rooms = new ArrayList(); + if(roomList != null) { + roomList.unregisterObserver(observer); + } + roomList = null; + notifyDataSetInvalidated(); + } + + private void reloadFromList(RoomList list) { + rooms = new ArrayList(roomList.getMap().values()); + Collections.sort(rooms, Collections.reverseOrder(Room.ID_COMPARATOR)); notifyDataSetChanged(); } @@ -99,17 +128,4 @@ return v; } - - public void itemAdded(Map map, String key, Room value) { - setList(map.values()); - } - - public void itemRemoved(Map map, String key, Room oldValue) { - setList(map.values()); - } - - public void itemReplaced(Map map, String key, Room oldValue, - Room newValue) { - setList(map.values()); - } } \ No newline at end of file diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomlistFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomlistFragment.java Sat Jul 21 14:56:52 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomlistFragment.java Mon Jul 23 00:17:06 2012 +0200 @@ -12,12 +12,17 @@ import android.os.IBinder; import android.support.v4.app.ListFragment; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.ListView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView; +import android.widget.Toast; -public class RoomlistFragment extends ListFragment { - private static final int AUTO_REFRESH_INTERVAL_MS = 10000; +public class RoomlistFragment extends ListFragment implements OnItemClickListener { + private static final int AUTO_REFRESH_INTERVAL_MS = 15000; private Netconn netconn; private RoomListAdapter adapter; @@ -40,6 +45,7 @@ Context.BIND_AUTO_CREATE); adapter = new RoomListAdapter(getActivity()); setListAdapter(adapter); + setHasOptionsMenu(true); } @Override @@ -50,6 +56,12 @@ } @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getListView().setOnItemClickListener(this); + } + + @Override public void onResume() { super.onResume(); if(netconn != null) { @@ -70,16 +82,39 @@ getActivity().unbindService(serviceConnection); } + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.lobby_roomlist_options, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.roomlist_refresh: + if(netconn != null) { + netconn.sendRoomlistRequest(); + } + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + public void onItemClick(AdapterView parent, View view, int position, long id) { + Toast.makeText(getActivity(), R.string.not_implemented_yet, Toast.LENGTH_SHORT).show(); + } + private ServiceConnection serviceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder binder) { netconn = ((NetplayBinder) binder).getNetconn(); - adapter.setList(netconn.roomList.getValues()); - netconn.roomList.observe(adapter); + adapter.setList(netconn.roomList); + autoRefreshTimer.start(); } public void onServiceDisconnected(ComponentName className) { // TODO navigate away - netconn.roomList.unobserve(adapter); + adapter.invalidate(); netconn = null; } }; diff -r 12fdfd2038d4 -r 641f11cdd319 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Signal.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Signal.java Sat Jul 21 14:56:52 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package org.hedgewars.hedgeroid.netplay; - -import java.util.List; - -public class Signal { - private List observers; - - public void addListener(CallbackType cb) { - observers.add(cb); - } - - public void removeListener(CallbackType cb) { - observers.remove(cb); - } -}