add move-up and move-down menuitems so group order can be controlled

by user.  Store position as array of rowids in preferences, and make
game info hashed by rowid rather than name.
This commit is contained in:
Eric House 2012-12-26 18:55:15 -08:00
parent 0a7fcb2de4
commit 0d9f1a3ba7
7 changed files with 141 additions and 88 deletions

View file

@ -7,6 +7,12 @@
<item android:id="@+id/list_group_rename"
android:title="@string/list_group_rename"
/>
<item android:id="@+id/list_group_moveup"
android:title="@string/list_group_moveup"
/>
<item android:id="@+id/list_group_movedown"
android:title="@string/list_group_movedown"
/>
<item android:id="@+id/list_group_delete"
android:title="@string/list_group_delete"
/>

View file

@ -72,6 +72,7 @@
<string name="key_relay_regid">key_relay_regid</string>
<string name="key_checked_sms">key_checked_sms</string>
<string name="key_default_group">key_default_group</string>
<string name="key_group_posns">key_group_posns</string>
<string name="key_notagain_sync">key_notagain_sync</string>
<string name="key_notagain_chat">key_notagain_chat</string>

View file

@ -2130,9 +2130,11 @@
<string name="newgroup_label">Name your new group:</string>
<string name="list_group_delete">Delete group</string>
<string name="list_group_rename">Rename group</string>
<string name="list_group_delete">Delete</string>
<string name="list_group_rename">Rename</string>
<string name="list_group_default">Put new games here</string>
<string name="list_group_moveup">Move up</string>
<string name="list_group_movedown">Move down</string>
<string name="group_cur_games">My games</string>
<string name="group_new_games">New games</string>

View file

@ -869,19 +869,19 @@ public class DBUtils {
// Groups stuff
public static class GameGroupInfo {
public long m_id;
public String m_name;
public boolean m_expanded;
public long m_lastMoveTime;
public boolean m_hasTurn;
public boolean m_turnLocal;
public GameGroupInfo( long id, boolean expanded ) {
m_id = id; m_expanded = expanded;
public GameGroupInfo( String name, boolean expanded ) {
m_name = name; m_expanded = expanded;
m_lastMoveTime = 0;
}
}
private static HashMap<String,GameGroupInfo> s_groupsCache = null;
private static HashMap<Long,GameGroupInfo> s_groupsCache = null;
private static void invalGroupsCache()
{
@ -890,11 +890,11 @@ public class DBUtils {
// Return map of string (group name) to info about all games in
// that group.
public static HashMap<String,GameGroupInfo> getGroups( Context context )
public static HashMap<Long,GameGroupInfo> getGroups( Context context )
{
if ( null == s_groupsCache ) {
HashMap<String,GameGroupInfo> result =
new HashMap<String,GameGroupInfo>();
HashMap<Long,GameGroupInfo> result =
new HashMap<Long,GameGroupInfo>();
initDB( context );
String[] columns = { ROW_ID, DBHelper.GROUPNAME,
DBHelper.EXPANDED };
@ -916,14 +916,15 @@ public class DBUtils {
long id = cursor.getLong( idIndex );
Assert.assertNotNull( name );
boolean expanded = 0 != cursor.getInt( expandedIndex );
result.put( name, new GameGroupInfo( id, expanded ) );
result.put( id, new GameGroupInfo( name, expanded ) );
}
cursor.close();
Iterator<GameGroupInfo> iter = result.values().iterator();
Iterator<Long> iter = result.keySet().iterator();
while ( iter.hasNext() ) {
GameGroupInfo ggi = iter.next();
readTurnInfo( db, ggi );
Long id = iter.next();
GameGroupInfo ggi = result.get( id );
readTurnInfo( db, id, ggi );
}
db.close();
@ -933,12 +934,13 @@ public class DBUtils {
return s_groupsCache;
} // getGroups
private static void readTurnInfo( SQLiteDatabase db, GameGroupInfo ggi )
private static void readTurnInfo( SQLiteDatabase db, long id,
GameGroupInfo ggi )
{
String[] columns = { DBHelper.LASTMOVE, DBHelper.GIFLAGS,
DBHelper.TURN };
String orderBy = DBHelper.LASTMOVE;
String selection = String.format( "%s=%d", DBHelper.GROUPID, ggi.m_id );
String selection = String.format( "%s=%d", DBHelper.GROUPID, id );
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
selection,
null, // args
@ -1042,7 +1044,7 @@ public class DBUtils {
{
long rowid = ROWID_NOTFOUND;
if ( null != name && 0 < name.length() ) {
HashMap<String,GameGroupInfo> gameInfo = getGroups( context );
HashMap<Long,GameGroupInfo> gameInfo = getGroups( context );
if ( null == gameInfo.get( name ) ) {
ContentValues values = new ContentValues();
values.put( DBHelper.GROUPNAME, name );

View file

@ -29,6 +29,7 @@ import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.TextView;
import java.util.HashMap; // class is not synchronized
import java.util.Iterator;
import java.util.Set;
import junit.framework.Assert;
@ -45,30 +46,58 @@ public class GameListAdapter implements ExpandableListAdapter {
private int m_fieldID;
private Handler m_handler;
private LoadItemCB m_cb;
private long[] m_positions;
public interface LoadItemCB {
public void itemClicked( long rowid, GameSummary summary );
}
public GameListAdapter( Context context, ExpandableListView list,
Handler handler, LoadItemCB cb, String fieldName )
Handler handler, LoadItemCB cb, long[] positions,
String fieldName )
{
// super( DBUtils.gamesList(context).length );
m_context = context;
m_list = list;
m_handler = handler;
m_cb = cb;
m_positions = positions;
m_factory = LayoutInflater.from( context );
m_fieldID = fieldToID( fieldName );
}
public long[] getPositions()
{
HashMap<Long,GameGroupInfo> info = gameInfo();
if ( null == m_positions || info.size() != m_positions.length ) {
m_positions = new long[info.size()];
Iterator<Long> iter = info.keySet().iterator();
for ( int ii = 0; ii < m_positions.length; ++ii ) {
m_positions[ii] = iter.next();
}
}
return m_positions;
}
public boolean moveGroup( long groupid, int moveBy )
{
int src = getGroupPosition( groupid );
int dest = src + moveBy;
long[] positions = getPositions();
boolean success = 0 <= dest && dest < positions.length;
if ( success ) {
long tmp = positions[src];
positions[src] = positions[dest];
positions[dest] = tmp;
}
return success;
}
public void expandGroups( ExpandableListView view )
{
HashMap<String,GameGroupInfo> info = gameInfo();
String[] names = groupNames();
for ( int ii = 0; ii < names.length; ++ii ) {
GameGroupInfo ggi = info.get( names[ii] );
HashMap<Long,GameGroupInfo> info = gameInfo();
for ( int ii = 0; ii < info.size(); ++ii ) {
GameGroupInfo ggi = getInfoForGroup( ii );
if ( ggi.m_expanded ) {
view.expandGroup( ii );
}
@ -78,13 +107,9 @@ public class GameListAdapter implements ExpandableListAdapter {
public long getRowIDFor( int group, int child )
{
long rowid = DBUtils.ROWID_NOTFOUND;
String[] groupNames = groupNames();
if ( group < groupNames.length ) {
String name = groupNames()[group];
long[] rows = getRows( name );
if ( child < rows.length ) {
rowid = rows[child];
}
long[] rows = getRows( getPositions()[group] );
if ( child < rows.length ) {
rowid = rows[child];
}
return rowid;
}
@ -100,24 +125,15 @@ public class GameListAdapter implements ExpandableListAdapter {
public long getGroupIDFor( int groupPos )
{
String name = groupNames()[groupPos];
GameGroupInfo ggi = gameInfo().get( name );
return ggi.m_id;
long id = getPositions()[groupPos];
return id;
}
public String groupName( long groupid )
{
String result = null;
String[] names = groupNames();
int index;
for ( index = 0; index < names.length; ++index ) {
GameGroupInfo ggi = gameInfo().get( names[index] );
if ( groupid == ggi.m_id ) {
result = names[index];
break;
}
}
return result;
HashMap<Long,GameGroupInfo> info = gameInfo();
GameGroupInfo ggi = info.get( groupid );
return ggi.m_name;
}
//////////////////////////////////////////////////////////////////////////
@ -158,7 +174,7 @@ public class GameListAdapter implements ExpandableListAdapter {
{
View result = null;
if ( null != convertView ) {
DbgUtils.logf( "getChildView gave non-null convertView" );
// DbgUtils.logf( "getChildView gave non-null convertView" );
if ( convertView instanceof GameListItem ) {
GameListItem child = (GameListItem)convertView;
long rowid = getRowIDFor( groupPosition, childPosition );
@ -193,15 +209,15 @@ public class GameListAdapter implements ExpandableListAdapter {
Utils.inflate(m_context, R.layout.game_list_group );
view.setGroupPosition( groupPosition );
String name = groupNames()[groupPosition];
if ( !isExpanded ) {
GameGroupInfo ggi = gameInfo().get( name );
GameGroupInfo ggi = getInfoForGroup( groupPosition );
view.setPct( m_handler, ggi.m_hasTurn, ggi.m_turnLocal,
ggi.m_lastMoveTime );
}
int nKids = getChildrenCount( groupPosition );
name = m_context.getString( R.string.group_namef, name, nKids );
String name = m_context.getString( R.string.group_namef,
groupNames()[groupPosition], nKids );
view.setText( name );
return view;
@ -222,9 +238,6 @@ public class GameListAdapter implements ExpandableListAdapter {
public Object getChild( int groupPosition, int childPosition )
{
return null;
// String name = groupNames()[groupPosition];
// long[] rows = getRows( name );
// return rows[childPosition];
}
public Object getGroup( int groupPosition )
@ -234,14 +247,13 @@ public class GameListAdapter implements ExpandableListAdapter {
public int getChildrenCount( int groupPosition )
{
String name = groupNames()[ groupPosition ];
long[] rows = getRows( name );
long[] rows = getRows( getPositions()[groupPosition] );
return rows.length;
}
public int getGroupCount()
{
return groupNames().length;
return gameInfo().size();
}
public void registerDataSetObserver( DataSetObserver obs ){}
@ -256,7 +268,7 @@ public class GameListAdapter implements ExpandableListAdapter {
groupPosition = child.getGroupPosition();
} else {
DbgUtils.logf( "no child for rowid %d", rowid );
// DbgUtils.logf( "no child for rowid %d", rowid );
GameListItem.inval( rowid );
m_list.invalidate();
@ -274,31 +286,28 @@ public class GameListAdapter implements ExpandableListAdapter {
}
}
private long[] getRows( String group )
private long[] getRows( long groupID )
{
GameGroupInfo ggi = gameInfo().get(group);
long groupID = ggi.m_id;
long[] rows = DBUtils.getGroupGames( m_context, groupID );
return rows;
return DBUtils.getGroupGames( m_context, groupID );
}
public String[] groupNames()
{
HashMap<String,GameGroupInfo> info = gameInfo();
Set<String> set = info.keySet();
String[] names = new String[ set.size() ];
set.toArray(names);
HashMap<Long,GameGroupInfo> info = gameInfo();
long[] positions = getPositions();
String[] names = new String[ positions.length ];
for ( int ii = 0; ii < names.length; ++ii ) {
names[ii] = info.get(positions[ii]).m_name;
}
return names;
}
public int getGroupPosition( long groupid )
{
int pos;
String[] names = groupNames();
HashMap<String, GameGroupInfo> info = gameInfo();
for ( pos = 0; pos < names.length; ++pos ) {
GameGroupInfo ggi = info.get( names[pos] );
if ( ggi.m_id == groupid ) {
int pos = -1;
long[] positions = getPositions();
for ( pos = 0; pos < positions.length; ++pos ) {
if ( positions[pos] == groupid ) {
break;
}
}
@ -310,15 +319,9 @@ public class GameListAdapter implements ExpandableListAdapter {
boolean changed = false;
int newID = fieldToID( fieldName );
if ( -1 == newID ) {
if ( XWApp.DEBUG ) {
DbgUtils.logf( "GameListAdapter.setField(): unable to match"
+ " fieldName %s", fieldName );
}
DbgUtils.logf( "GameListAdapter.setField(): unable to match"
+ " fieldName %s", fieldName );
} else if ( m_fieldID != newID ) {
if ( XWApp.DEBUG ) {
DbgUtils.logf( "setField: clearing views cache for change"
+ " from %d to %d", m_fieldID, newID );
}
m_fieldID = newID;
// return true so caller will do onContentChanged.
// There's no other way to signal GameListItem instances
@ -330,8 +333,7 @@ public class GameListAdapter implements ExpandableListAdapter {
private GameGroupInfo getInfoForGroup( int groupPosition )
{
String name = groupNames()[groupPosition];
return gameInfo().get( name );
return gameInfo().get( getPositions()[groupPosition] );
}
private GameListItem getGameItemFor( long rowid )
@ -395,9 +397,8 @@ public class GameListAdapter implements ExpandableListAdapter {
}
}
private HashMap<String,GameGroupInfo> gameInfo()
private HashMap<Long,GameGroupInfo> gameInfo()
{
return DBUtils.getGroups( m_context );
}
}

View file

@ -361,8 +361,10 @@ public class GamesList extends XWExpandableListActivity
});
String field = CommonPrefs.getSummaryField( this );
long[] positions = XWPrefs.getGroupPositions( this );
m_adapter = new GameListAdapter( this, getExpandableListView(),
new Handler(), this, field );
new Handler(), this, positions,
field );
setListAdapter( m_adapter );
m_adapter.expandGroups( getExpandableListView() );
@ -420,7 +422,8 @@ public class GamesList extends XWExpandableListActivity
// (TelephonyManager)getSystemService( Context.TELEPHONY_SERVICE );
// mgr.listen( m_phoneStateListener, PhoneStateListener.LISTEN_NONE );
// m_phoneStateListener = null;
long[] positions = m_adapter.getPositions();
XWPrefs.setGroupPositions( this, positions );
super.onStop();
}
@ -583,18 +586,22 @@ public class GamesList extends XWExpandableListActivity
long packedPos = info.packedPosition;
int childPos = ExpandableListView.getPackedPositionChild( packedPos );
String name;
if ( 0 <= childPos ) {
MenuInflater inflater = getMenuInflater();
inflater.inflate( R.menu.games_list_item_menu, menu );
long rowid = m_adapter.getRowIDFor( packedPos );
String title = GameUtils.getName( this, rowid );
menu.setHeaderTitle( getString( R.string.game_item_menu_titlef,
title ) );
name = GameUtils.getName( this, rowid );
} else {
MenuInflater inflater = getMenuInflater();
inflater.inflate( R.menu.games_list_group_menu, menu );
int pos = ExpandableListView.getPackedPositionGroup( packedPos );
name = m_adapter.groupNames()[pos];
}
menu.setHeaderTitle( getString( R.string.game_item_menu_titlef,
name ) );
}
@Override
@ -815,6 +822,18 @@ public class GamesList extends XWExpandableListActivity
case R.id.list_group_default:
XWPrefs.setDefaultNewGameGroup( this, m_groupid );
break;
case R.id.list_group_moveup:
if ( m_adapter.moveGroup( m_groupid, -1 ) ) {
onContentChanged();
}
break;
case R.id.list_group_movedown:
if ( m_adapter.moveGroup( m_groupid, 1 ) ) {
onContentChanged();
}
break;
default:
handled = false;
}

View file

@ -26,7 +26,6 @@ import android.preference.PreferenceManager;
import android.text.TextUtils;
import com.google.android.gcm.GCMRegistrar;
import java.util.ArrayList;
import java.util.ArrayList;
public class XWPrefs {
@ -305,6 +304,29 @@ public class XWPrefs {
setPrefsLong( context, R.string.key_default_group, val );
}
public static void setGroupPositions( Context context, long[] posns )
{
String[] asStrs = new String[posns.length];
for ( int ii = 0; ii < posns.length; ++ii ) {
asStrs[ii] = String.format( "%d", posns[ii] );
}
setPrefsStringArray( context, R.string.key_group_posns, asStrs );
}
public static long[] getGroupPositions( Context context )
{
long[] posns = null;
String[] longStrs = getPrefsStringArray( context,
R.string.key_group_posns );
if ( null != longStrs ) {
posns = new long[longStrs.length];
for ( int ii = 0; ii < longStrs.length; ++ii ) {
posns[ii] = Long.parseLong(longStrs[ii]);
}
}
return posns;
}
protected static String getPrefsString( Context context, int keyID )
{
String key = context.getString( keyID );