Hedgeroid: Reworked player and room lists, added menus, added playername query
Still work in progress...
--- 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 @@
</activity>
<activity
android:name=".netplay.LobbyActivity"
- android:label="@string/title_activity_lobby" >
+ android:label="@string/title_activity_lobby"
+ android:screenOrientation="landscape"
+
+ android:windowSoftInputMode="adjustResize" >
</activity>
</application>
</manifest>
\ No newline at end of file
--- 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">
<TextView
android:id="@+id/roomname"
--- a/project_files/Android-build/SDL-android-project/res/layout/listview_room.xml Sat Jul 21 14:56:52 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/layout/listview_room.xml Mon Jul 23 00:17:06 2012 +0200
@@ -2,7 +2,9 @@
<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:mode="twoLine">
+ android:mode="twoLine"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp">
<TextView
android:id="@android:id/text1"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/menu/lobby_options.xml Mon Jul 23 00:17:06 2012 +0200
@@ -0,0 +1,6 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:id="@+id/room_create"
+ android:title="@string/lobby_roomlistmenu_create"
+ android:showAsAction="ifRoom" />
+</menu>
\ No newline at end of file
--- /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 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:id="@+id/player_info"
+ android:title="@string/lobby_playerlist_contextmenu_info">
+ </item>
+ <item
+ android:id="@+id/player_follow"
+ android:title="@string/lobby_playerlist_contextmenu_follow">
+ </item>
+</menu>
\ No newline at end of file
--- /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 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:id="@+id/roomlist_refresh"
+ android:title="@string/lobby_roomlistmenu_refresh"
+ android:showAsAction="ifRoom" />
+</menu>
\ No newline at end of file
--- 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 @@
<string name="roomlist_header_owner">Owner</string>
<string name="roomlist_header_map">Map</string>
<string name="roomlist_header_scheme">Rules</string>
- <string name="roomlist_header_weapons">Ammo</string>
+ <string name="roomlist_header_weapons">Weapons</string>
<string name="roomlist_owner">by %1$s</string>
<string name="roomlist_map">Map: %1$s</string>
@@ -86,4 +86,16 @@
<string name="log_player_join">%1$s has joined.</string>
<string name="log_player_leave">%1$s has left.</string>
<string name="log_player_leave_with_msg">%1$s has left (%2$s).</string>
+
+ <!-- Start netgame dialog -->
+ <string name="start_netgame_dialog_title">Connect</string>
+ <string name="start_netgame_dialog_message">Please select a username.</string>
+ <string name="start_netgame_dialog_playername_hint">Enter a username here</string>
+
+ <string name="lobby_playerlist_contextmenu_info">Info (shown in chat)</string>
+ <string name="lobby_playerlist_contextmenu_follow">Follow</string>
+ <string name="lobby_roomlistmenu_create">Create room</string>
+ <string name="lobby_roomlistmenu_refresh">Refresh</string>
+
+ <string name="not_implemented_yet">Sorry, not implemented yet. :(</string>
</resources>
--- 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();
--- 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;
}
};
--- 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)));
--- 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
--- 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<K,V> {
- private LinkedHashMap<K,V> map = new LinkedHashMap<K,V>();
- private List<Observer<K,V>> observers = new LinkedList<Observer<K,V>>();
-
- public Collection<V> getValues() {
- return Collections.unmodifiableCollection(map.values());
- }
-
- public Map<K,V> getMap() {
- return Collections.unmodifiableMap(map);
- }
-
- public void observe(Observer<K,V> observer) {
- observers.add(observer);
- }
-
- public void unobserve(Observer<K,V> 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<K,V> unmodifiableMap = Collections.unmodifiableMap(map);
- if(oldValue != null) {
- for(Observer<K,V> o : observers) {
- o.itemReplaced(unmodifiableMap, key, oldValue, value);
- }
- } else {
- for(Observer<K,V> o : observers) {
- o.itemAdded(unmodifiableMap, key, value);
- }
- }
- }
-
- public void remove(K key) {
- V oldValue = map.remove(key);
- if(oldValue != null) {
- Map<K,V> unmodifiableMap = Collections.unmodifiableMap(map);
- for(Observer<K,V> o : observers) {
- o.itemRemoved(unmodifiableMap, key, oldValue);
- }
- }
- }
-
- public static interface Observer<K,V> {
- void itemAdded(Map<K,V> map, K key, V value);
- void itemRemoved(Map<K,V> map, K key, V oldValue);
- void itemReplaced(Map<K,V> map, K key, V oldValue, V newValue);
- }
-}
--- 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<Player> {
+ private static final class ByNameComparator implements Comparator<Player> {
public int compare(Player lhs, Player rhs) {
return lhs.name.compareToIgnoreCase(rhs.name);
}
--- 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<String, Player> {
+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<String, Player> players = new TreeMap<String, Player>();
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<String, Player> {}
+ public void removePlayer(String name) {
+ if(players.remove(name) != null) {
+ notifyChanged();
+ }
+ }
+
+ public Map<String, Player> getMap() {
+ return Collections.unmodifiableMap(players);
+ }
}
--- 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<Player> players = new ArrayList<Player>();
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<String, Player> map, String key, Player value) {
- setPlayerList(map.values());
- }
-
- public void itemRemoved(Map<String, Player> map, String key, Player oldValue) {
- setPlayerList(map.values());
- }
-
- public void itemReplaced(Map<String, Player> 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<Player> players) {
- this.players = new ArrayList<Player>(players);
- Collections.sort(this.players, Player.nameComparator);
+ public void invalidate() {
+ players = new ArrayList<Player>();
+ if(playerList != null) {
+ playerList.unregisterObserver(observer);
+ }
+ playerList = null;
+ notifyDataSetInvalidated();
+ }
+
+ private void reloadFromList(PlayerList list) {
+ players = new ArrayList<Player>(list.getMap().values());
+ Collections.sort(players, Player.NAME_COMPARATOR);
notifyDataSetChanged();
}
--- 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;
}
};
--- 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<Room> 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<Room> {
+ public int compare(Room lhs, Room rhs) {
+ return lhs.id<rhs.id ? -1 : lhs.id>rhs.id ? 1 : 0;
+ }
+ }
}
--- 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<String, Room> {
+public class RoomList extends DataSetObservable {
private long nextId = 1;
+ private Map<String, Room> rooms = new TreeMap<String, Room>();
+
+ public void updateList(RoomPtr[] roomPtrs) {
+ Map<String, Room> newMap = new TreeMap<String, Room>();
+ 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<String, Room> { }
+
+ public Map<String, Room> 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);
+ }
}
--- 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<Room> rooms = new ArrayList<Room>();
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<Room> rooms) {
- this.rooms = new ArrayList<Room>(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<Room>();
+ if(roomList != null) {
+ roomList.unregisterObserver(observer);
+ }
+ roomList = null;
+ notifyDataSetInvalidated();
+ }
+
+ private void reloadFromList(RoomList list) {
+ rooms = new ArrayList<Room>(roomList.getMap().values());
+ Collections.sort(rooms, Collections.reverseOrder(Room.ID_COMPARATOR));
notifyDataSetChanged();
}
@@ -99,17 +128,4 @@
return v;
}
-
- public void itemAdded(Map<String, Room> map, String key, Room value) {
- setList(map.values());
- }
-
- public void itemRemoved(Map<String, Room> map, String key, Room oldValue) {
- setList(map.values());
- }
-
- public void itemReplaced(Map<String, Room> map, String key, Room oldValue,
- Room newValue) {
- setList(map.values());
- }
}
\ No newline at end of file
--- 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;
}
};
--- 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<CallbackType> {
- private List<CallbackType> observers;
-
- public void addListener(CallbackType cb) {
- observers.add(cb);
- }
-
- public void removeListener(CallbackType cb) {
- observers.remove(cb);
- }
-}