diff --git a/xwords4/android/XWords4/jni/anddict.c b/xwords4/android/XWords4/jni/anddict.c index 1e6ffe3c7..84ce56000 100644 --- a/xwords4/android/XWords4/jni/anddict.c +++ b/xwords4/android/XWords4/jni/anddict.c @@ -487,7 +487,7 @@ makeDict( MPFORMAL JNIEnv *env, JNIUtilCtxt* jniutil, jstring jname, anddict->bytes = (*env)->GetByteArrayElements( env, anddict->byteArray, NULL ); } else { - anddict->byteArray = NULL; + XP_ASSERT( NULL == anddict->byteArray ); const char* path = (*env)->GetStringUTFChars( env, jpath, NULL ); struct stat statbuf; diff --git a/xwords4/android/XWords4/res/layout/game_list_item.xml b/xwords4/android/XWords4/res/layout/game_list_item.xml index 62555d926..d5e06ef77 100644 --- a/xwords4/android/XWords4/res/layout/game_list_item.xml +++ b/xwords4/android/XWords4/res/layout/game_list_item.xml @@ -58,25 +58,12 @@ android:padding="4sp"> - - - - - - - - + /> + + + diff --git a/xwords4/android/XWords4/res/layout/player_edit.xml b/xwords4/android/XWords4/res/layout/player_edit.xml index 29a5863a9..cf5427b14 100644 --- a/xwords4/android/XWords4/res/layout/player_edit.xml +++ b/xwords4/android/XWords4/res/layout/player_edit.xml @@ -72,7 +72,6 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:drawSelectorOnTop="true" - android:prompt="@string/title_dicts_list" /> Make a game's language one of several configurable attributes that can be displayed along with the game +
  • Display relay connection state as being in one of three phases: + configured, connected, and with all players present.
  • +
  • Fix rename of games to work when keyboard opened while dialog up.
  • diff --git a/xwords4/android/XWords4/res/values/strings.xml b/xwords4/android/XWords4/res/values/strings.xml index 84f86a24d..521660c42 100644 --- a/xwords4/android/XWords4/res/values/strings.xml +++ b/xwords4/android/XWords4/res/values/strings.xml @@ -68,6 +68,7 @@ Html Name: + Installed wordlists (in %s) FYI... New user info @@ -364,7 +365,11 @@ check off-device players. Modified first player. - Connecting via Relay, room \"%s\" + Configured for room + \"%s\" + Waiting for players in room + \"%s\" + Game in play in room \"%s\" Game over %d moves played diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java index 436809680..ff98d7495 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -73,6 +73,8 @@ public class BoardActivity extends XWActivity private static final int CHAT_REQUEST = 1; private static final int SCREEN_ON_TIME = 10 * 60 * 1000; // 10 mins + private static final int UNDO_LAST_ACTION = 1; + private static final String DLG_TITLE = "DLG_TITLE"; private static final String DLG_TITLESTR = "DLG_TITLESTR"; private static final String DLG_BYTES = "DLG_BYTES"; @@ -157,7 +159,7 @@ public class BoardActivity extends XWActivity ab.setNegativeButton( R.string.button_retry, lstnr ); } dialog = ab.create(); - setRemoveOnDismiss( dialog, id ); + Utils.setRemoveOnDismiss( this, dialog, id ); break; case DLG_DELETED: @@ -258,14 +260,7 @@ public class BoardActivity extends XWActivity handle(JNICmd.CMD_ENDGAME); } }) - .setNegativeButton( R.string.button_no, - new DialogInterface.OnClickListener() { - public void - onClick( DialogInterface dlg, - int item ) { - // do nothing - } - }) + .setNegativeButton( R.string.button_no, null ) .create(); break; case DLG_INVITE: @@ -516,14 +511,7 @@ public class BoardActivity extends XWActivity // cmd = JNIThread.JNICmd.CMD_UNDO_CUR; // break; case R.id.board_menu_undo_last: - showConfirmThen( R.string.confirm_undo_last, - new DialogInterface.OnClickListener() { - public void onClick( DialogInterface dlg, - int whichButton ) { - m_jniThread.handle( JNIThread.JNICmd. - CMD_UNDO_LAST ); - } - } ); + showConfirmThen( R.string.confirm_undo_last, UNDO_LAST_ACTION ); break; case R.id.board_menu_values: cmd = JNIThread.JNICmd.CMD_VALUES; @@ -575,6 +563,22 @@ public class BoardActivity extends XWActivity return handled; } + ////////////////////////////////////////////////// + // DlgDelegate.DlgClickNotify interface + ////////////////////////////////////////////////// + + public void buttonClicked( int id, boolean cancelled ) + { + switch ( id ) { + case UNDO_LAST_ACTION: + if ( !cancelled ) { + m_jniThread.handle( JNIThread.JNICmd.CMD_UNDO_LAST ); + } + break; + default: + Assert.fail(); + } + } ////////////////////////////////////////////////// // TransportProcs.TPMsgHandler interface @@ -1079,31 +1083,32 @@ public class BoardActivity extends XWActivity langName ); } - m_jniThread = new - JNIThread( m_jniGamePtr, m_gi, m_view, m_gameLock, this, - new Handler() { - public void handleMessage( Message msg ) { - switch( msg.what ) { - case JNIThread.DRAW: - m_view.invalidate(); - break; - case JNIThread.DIALOG: - m_dlgBytes = (String)msg.obj; - m_dlgTitle = msg.arg1; - showDialog( DLG_OKONLY ); - break; - case JNIThread.QUERY_ENDGAME: - showDialog( QUERY_ENDGAME ); - break; - case JNIThread.TOOLBAR_STATES: - if ( null != m_jniThread ) { - m_gsi = m_jniThread.getGameStateInfo(); - updateToolbar(); - } - break; - } - } - } ); + Handler handler = new Handler() { + public void handleMessage( Message msg ) { + switch( msg.what ) { + case JNIThread.DRAW: + m_view.invalidate(); + break; + case JNIThread.DIALOG: + m_dlgBytes = (String)msg.obj; + m_dlgTitle = msg.arg1; + showDialog( DLG_OKONLY ); + break; + case JNIThread.QUERY_ENDGAME: + showDialog( QUERY_ENDGAME ); + break; + case JNIThread.TOOLBAR_STATES: + if ( null != m_jniThread ) { + m_gsi = + m_jniThread.getGameStateInfo(); + updateToolbar(); + } + break; + } + } + }; + m_jniThread = new JNIThread( m_jniGamePtr, m_gi, m_view, + m_gameLock, this, handler ); // see http://stackoverflow.com/questions/680180/where-to-stop-\ // destroy-threads-in-android-service-class m_jniThread.setDaemon( true ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsActivity.java index 45aabc836..921664968 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsActivity.java @@ -56,11 +56,20 @@ import org.eehouse.android.xw4.jni.CommonPrefs; public class DictsActivity extends ExpandableListActivity implements View.OnClickListener, XWListItem.DeleteCallback, - SDCardWatcher.SDCardNotifiee { + SDCardWatcher.SDCardNotifiee, DlgDelegate.DlgClickNotify { private static final String DICT_DOLAUNCH = "do_launch"; private static final String DICT_LANG_EXTRA = "use_lang"; private static final String DICT_NAME_EXTRA = "use_dict"; + private static final String PACKED_POSITION = "packed_position"; + private static final String DELETE_DICT = "delete_dict"; + private static final String NAME = "name"; + private static final String LANG = "lang"; + private static final String MOVEFROMLOC = "movefromloc"; + private static final String MOVETOLOC = "movetoloc"; + + // For new callback alternative + private static final int DELETE_DICT_ACTION = 1; private static final int PICK_STORAGE = DlgDelegate.DIALOG_LAST + 1; private static final int MOVE_DICT = DlgDelegate.DIALOG_LAST + 2; @@ -68,21 +77,23 @@ public class DictsActivity extends ExpandableListActivity private int m_lang = 0; private String[] m_langs; private String m_name = null; + private String m_deleteDict = null; private String m_download; private ExpandableListView m_expView; private DlgDelegate m_delegate; private String[] m_locNames; + private DictListAdapter m_adapter; - private XWListItem m_rowView; - GameUtils.DictLoc m_moveFromLoc; - GameUtils.DictLoc m_moveToLoc; + private long m_packedPosition; + private GameUtils.DictLoc m_moveFromLoc; + private GameUtils.DictLoc m_moveToLoc; private SDCardWatcher m_cardWatcher; - private String m_moveName; private LayoutInflater m_factory; private class DictListAdapter implements ExpandableListAdapter { private Context m_context; + private XWListItem[][] m_cache; public DictListAdapter( Context context ) { //super( context, m_dicts.length ); @@ -105,29 +116,41 @@ public class DictsActivity extends ExpandableListActivity boolean isLastChild, View convertView, ViewGroup parent) { - int lang = (int)getGroupId( groupPosition ); - String[] dicts = DictLangCache.getHaveLang( m_context, lang ); - String text; - boolean canDelete = false; - if ( null != dicts && childPosition < dicts.length ) { - text = dicts[childPosition]; - canDelete = !GameUtils.dictIsBuiltin( DictsActivity.this, - text ); - } else { - text = m_download; - } - XWListItem view = - (XWListItem)m_factory.inflate( R.layout.list_item, null ); - view.setText( text ); - if ( canDelete ) { - view.setDeleteCallback( DictsActivity.this ); + return getChildView( groupPosition, childPosition ); + } + + private View getChildView( int groupPosition, int childPosition ) + { + XWListItem view = null; + if ( null != m_cache && null != m_cache[groupPosition] ) { + view = m_cache[groupPosition][childPosition]; } - GameUtils.DictLoc loc = - GameUtils.getDictLoc( DictsActivity.this, text ); - view.setComment( m_locNames[loc.ordinal()] ); - view.cache( loc ); + if ( null == view ) { + int lang = (int)getGroupId( groupPosition ); + String[] dicts = DictLangCache.getHaveLang( m_context, lang ); + String text; + boolean canDelete = false; + if ( null != dicts && childPosition < dicts.length ) { + text = dicts[childPosition]; + canDelete = !GameUtils.dictIsBuiltin( DictsActivity.this, + text ); + } else { + text = m_download; + } + view = (XWListItem)m_factory.inflate( R.layout.list_item, null ); + view.setText( text ); + if ( canDelete ) { + view.setDeleteCallback( DictsActivity.this ); + } + GameUtils.DictLoc loc = + GameUtils.getDictLoc( DictsActivity.this, text ); + view.setComment( m_locNames[loc.ordinal()] ); + view.cache( loc ); + + addToCache( groupPosition, childPosition, view ); + } return view; } @@ -188,17 +211,40 @@ public class DictsActivity extends ExpandableListActivity public void onGroupExpanded(int groupPosition){} public void registerDataSetObserver( DataSetObserver obs ){} public void unregisterDataSetObserver( DataSetObserver obs ){} + + protected XWListItem getSelChildView() + { + int groupPosition = + ExpandableListView.getPackedPositionGroup( m_packedPosition ); + int childPosition = + ExpandableListView.getPackedPositionChild( m_packedPosition ); + return (XWListItem)getChildView( groupPosition, childPosition ); + } + + private void addToCache( int group, int child, XWListItem view ) + { + if ( null == m_cache ) { + m_cache = new XWListItem[getGroupCount()][]; + } + if ( null == m_cache[group] ) { + m_cache[group] = new XWListItem[getChildrenCount(group)]; + } + Assert.assertTrue( null == m_cache[group][child] ); + m_cache[group][child] = view; + } } @Override protected Dialog onCreateDialog( int id ) { - Dialog dialog; DialogInterface.OnClickListener lstnr; + Dialog dialog; + String format; + String message; + boolean doRemove = true; switch( id ) { case PICK_STORAGE: - lstnr = new DialogInterface.OnClickListener() { public void onClick( DialogInterface dlg, int item ) { startDownload( m_lang, m_name, item != @@ -216,21 +262,28 @@ public class DictsActivity extends ExpandableListActivity case MOVE_DICT: lstnr = new DialogInterface.OnClickListener() { public void onClick( DialogInterface dlg, int item ) { + XWListItem rowView = m_adapter.getSelChildView(); if ( GameUtils.moveDict( DictsActivity.this, - m_moveName, + rowView.getText(), m_moveFromLoc, m_moveToLoc ) ) { - m_rowView. + rowView. setComment( m_locNames[m_moveToLoc.ordinal()]); - m_rowView.cache( m_moveToLoc ); - m_rowView.invalidate(); + rowView.cache( m_moveToLoc ); + rowView.invalidate(); } else { Utils.logf( "moveDict failed" ); } } }; + format = getString( R.string.move_dictf ); + message = String.format( format, + m_adapter.getSelChildView().getText(), + m_locNames[ m_moveFromLoc.ordinal() ], + m_locNames[ m_moveToLoc.ordinal() ] ); + dialog = new AlertDialog.Builder( this ) - .setMessage( "" ) // will set later + .setMessage( message ) .setPositiveButton( R.string.button_ok, lstnr ) .setNegativeButton( R.string.button_cancel, null ) .create(); @@ -240,18 +293,22 @@ public class DictsActivity extends ExpandableListActivity public void onClick( DialogInterface dlg, int item ) { if ( DialogInterface.BUTTON_NEGATIVE == item || DialogInterface.BUTTON_POSITIVE == item ) { - setDefault( R.string.key_default_dict, m_rowView ); + setDefault( R.string.key_default_dict ); } if ( DialogInterface.BUTTON_NEGATIVE == item || DialogInterface.BUTTON_NEUTRAL == item ) { - setDefault( R.string.key_default_robodict, - m_rowView ); + setDefault( R.string.key_default_robodict ); } } }; + XWListItem rowView = m_adapter.getSelChildView(); + String lang = + DictLangCache.getLangName( this, rowView.getText() ); + format = getString( R.string.set_default_messagef ); + message = String.format( format, lang ); dialog = new AlertDialog.Builder( this ) .setTitle( R.string.query_title ) - .setMessage( "" ) // or can't change it later! + .setMessage( message ) .setPositiveButton( R.string.button_default_human, lstnr ) .setNeutralButton( R.string.button_default_robot, lstnr ) .setNegativeButton( R.string.button_default_both, lstnr ) @@ -259,49 +316,34 @@ public class DictsActivity extends ExpandableListActivity break; default: dialog = m_delegate.onCreateDialog( id ); + doRemove = false; break; } + + if ( doRemove && null != dialog ) { + Utils.setRemoveOnDismiss( this, dialog, id ); + } + return dialog; - } + } // onCreateDialog @Override - public void onPrepareDialog( int id, Dialog dialog ) + protected void onPrepareDialog( int id, Dialog dialog ) { - AlertDialog ad = (AlertDialog)dialog; - String format; - String message; - - switch( id ) { - case PICK_STORAGE: - break; - case MOVE_DICT: - format = getString( R.string.move_dictf ); - message = String.format( format, m_moveName, - m_locNames[ m_moveFromLoc.ordinal() ], - m_locNames[ m_moveToLoc.ordinal() ] ); - ad.setMessage( message ); - break; - case SET_DEFAULT: - String lang = - DictLangCache.getLangName( this, m_rowView.getText() ); - format = getString( R.string.set_default_messagef ); - message = String.format( format, lang ); - ad.setMessage( message ); - break; - default: - m_delegate.onPrepareDialog( id, dialog ); - } + super.onPrepareDialog( id, dialog ); + m_delegate.onPrepareDialog( id, dialog ); } @Override - protected void onCreate(Bundle savedInstanceState) + protected void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); + getBundledData( savedInstanceState ); Resources res = getResources(); m_locNames = res.getStringArray( R.array.loc_names ); - m_delegate = new DlgDelegate( this ); + m_delegate = new DlgDelegate( this, this, savedInstanceState ); m_factory = LayoutInflater.from( this ); m_download = getString( R.string.download_dicts ); @@ -338,6 +380,44 @@ public class DictsActivity extends ExpandableListActivity expandGroups(); } + @Override + protected void onSaveInstanceState( Bundle outState ) + { + super.onSaveInstanceState( outState ); + m_delegate.onSaveInstanceState( outState ); + + outState.putLong( PACKED_POSITION, m_packedPosition ); + outState.putString( NAME, m_name ); + outState.putInt( LANG, m_lang ); + outState.putString( DELETE_DICT, m_deleteDict ); + if ( null != m_moveFromLoc ) { + outState.putInt( MOVEFROMLOC, m_moveFromLoc.ordinal() ); + } + if ( null != m_moveToLoc ) { + outState.putInt( MOVETOLOC, m_moveToLoc.ordinal() ); + } + } + + private void getBundledData( Bundle savedInstanceState ) + { + if ( null != savedInstanceState ) { + m_packedPosition = savedInstanceState.getLong( PACKED_POSITION ); + m_name = savedInstanceState.getString( NAME ); + m_lang = savedInstanceState.getInt( LANG ); + m_deleteDict = savedInstanceState.getString( DELETE_DICT ); + + int tmp = savedInstanceState.getInt( MOVEFROMLOC, -1 ); + if ( -1 != tmp ) { + m_moveFromLoc = GameUtils.DictLoc.values()[tmp]; + } + tmp = savedInstanceState.getInt( MOVETOLOC, -1 ); + if ( -1 != tmp ) { + m_moveToLoc = GameUtils.DictLoc.values()[tmp]; + } + } + } + + @Override protected void onPause() { m_cardWatcher.close(); m_cardWatcher = null; @@ -395,14 +475,14 @@ public class DictsActivity extends ExpandableListActivity return false; } - XWListItem row = (XWListItem)info.targetView; + m_packedPosition = info.packedPosition; + int id = item.getItemId(); switch( id ) { case R.id.dicts_item_move: - askMoveDict( row ); + askMoveDict( (XWListItem)info.targetView ); break; case R.id.dicts_item_select: - m_rowView = row; showDialog( SET_DEFAULT ); break; case R.id.dicts_item_details: @@ -413,13 +493,14 @@ public class DictsActivity extends ExpandableListActivity return handled; } - private void setDefault( int keyId, final XWListItem text ) + private void setDefault( int keyId ) { + XWListItem view = m_adapter.getSelChildView(); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences( this ); SharedPreferences.Editor editor = sp.edit(); String key = getString( keyId ); - String name = text.getText(); + String name = view.getText(); editor.putString( key, name ); editor.commit(); } @@ -429,32 +510,25 @@ public class DictsActivity extends ExpandableListActivity // options for YY? private void askMoveDict( XWListItem item ) { - m_rowView = item; m_moveFromLoc = (GameUtils.DictLoc)item.getCached(); if ( m_moveFromLoc == GameUtils.DictLoc.INTERNAL ) { m_moveToLoc = GameUtils.DictLoc.EXTERNAL; } else { m_moveToLoc = GameUtils.DictLoc.INTERNAL; } - m_moveName = item.getText(); showDialog( MOVE_DICT ); } // XWListItem.DeleteCallback interface - public void deleteCalled( int myPosition, final String dict ) + public void deleteCalled( int myPosition, String dict ) { int code = DictLangCache.getDictLangCode( this, dict ); String lang = DictLangCache.getLangName( this, code ); int nGames = DBUtils.countGamesUsing( this, code ); String msg = String.format( getString( R.string.confirm_delete_dictf ), dict ); - DialogInterface.OnClickListener action = - new DialogInterface.OnClickListener() { - public void onClick( DialogInterface dlg, int item ) { - deleteDict( dict ); - } - }; + m_deleteDict = dict; if ( nGames > 0 ) { int fmt; @@ -466,7 +540,7 @@ public class DictsActivity extends ExpandableListActivity msg += String.format( getString(fmt), lang ); } - m_delegate.showConfirmThen( msg, action ); + m_delegate.showConfirmThen( msg, DELETE_DICT_ACTION ); } // SDCardWatcher.SDCardNotifiee interface @@ -476,6 +550,20 @@ public class DictsActivity extends ExpandableListActivity expandGroups(); } + // DlgDelegate.DlgClickNotify interface + public void dlgButtonClicked( int id, boolean cancelled ) + { + switch( id ) { + case DELETE_DICT_ACTION: + if ( !cancelled ) { + deleteDict( m_deleteDict ); + } + break; + default: + Assert.fail(); + } + } + private void deleteDict( String dict ) { GameUtils.deleteDict( this, dict ); @@ -508,9 +596,8 @@ public class DictsActivity extends ExpandableListActivity private void mkListAdapter() { m_langs = DictLangCache.listLangs( this ); - //m_langs = DictLangCache.getLangNames( this ); - ExpandableListAdapter adapter = new DictListAdapter( this ); - setListAdapter( adapter ); + m_adapter = new DictListAdapter( this ); + setListAdapter( m_adapter ); } private void expandGroups() diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DlgDelegate.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DlgDelegate.java index abc2ee79f..8ab96b1c2 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DlgDelegate.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DlgDelegate.java @@ -21,14 +21,16 @@ package org.eehouse.android.xw4; import android.app.Activity; +import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; -import junit.framework.Assert; +import android.os.Bundle; import android.view.View; import android.widget.TextView; import android.widget.Toast; -import android.app.AlertDialog; + +import junit.framework.Assert; import org.eehouse.android.xw4.jni.CommonPrefs; @@ -43,21 +45,41 @@ public class DlgDelegate { public static final int DLG_DICTGONE = 6; public static final int DIALOG_LAST = DLG_DICTGONE; + public static final String MSG = "msg"; + public static final String CALLBACK = "callback"; + public static final String MSGID = "msgid"; + + public interface DlgClickNotify { + void dlgButtonClicked( int id, boolean cancelled ); + } + private int m_msgID; + private int m_cbckID; private String m_msg; private Runnable m_proc = null; private int m_prefsKey; private Activity m_activity; + private DlgClickNotify m_clickCallback; private String m_dictName = null; - DialogInterface.OnClickListener m_then; - public interface TextOrHtmlClicked { - public void clicked( boolean choseText ); - }; - private TextOrHtmlClicked m_txt_or_html; - - public DlgDelegate( Activity activity ) { + public DlgDelegate( Activity activity, DlgClickNotify callback, + Bundle bundle ) + { m_activity = activity; + m_clickCallback = callback; + + if ( null != bundle ) { + m_msg = bundle.getString( MSG ); + m_cbckID = bundle.getInt( CALLBACK ); + m_msgID = bundle.getInt( MSGID ); + } + } + + public void onSaveInstanceState( Bundle outState ) + { + outState.putString( MSG, m_msg ); + outState.putInt( CALLBACK, m_cbckID ); + outState.putInt( MSGID, m_msgID ); } public Dialog onCreateDialog( int id ) @@ -86,17 +108,6 @@ public class DlgDelegate { return dialog; } - protected void setRemoveOnDismiss( Dialog dialog, final int id ) - { - dialog.setOnDismissListener( new DialogInterface.OnDismissListener() { - public void onDismiss( DialogInterface di ) { - Utils.logf( "%s.onDismiss() called", - getClass().getName() ); - m_activity.removeDialog( id ); - } - } ); - } - public void onPrepareDialog( int id, Dialog dialog ) { AlertDialog ad = (AlertDialog)dialog; @@ -114,27 +125,18 @@ public class DlgDelegate { ad.setMessage( m_activity.getString(m_msgID) ); break; case CONFIRM_THEN: - // I'm getting an occasional 0 here on device only. May - // be related to screen orientation changes. Let's be safe ad.setMessage( m_msg ); - ad.setButton( AlertDialog.BUTTON_POSITIVE, - m_activity.getString( R.string.button_ok ), m_then ); - break; - case TEXT_OR_HTML_THEN: lstnr = new DialogInterface.OnClickListener() { public void onClick( DialogInterface dlg, int button ) { - if ( null != m_txt_or_html ) { - m_txt_or_html. - clicked( button == AlertDialog.BUTTON_POSITIVE ); - } + boolean cancelled = + button == DialogInterface.BUTTON_NEGATIVE; + m_clickCallback.dlgButtonClicked( m_cbckID, cancelled ); } }; ad.setButton( AlertDialog.BUTTON_POSITIVE, - m_activity.getString( R.string.button_text ), - lstnr ); - ad.setButton( AlertDialog.BUTTON_NEGATIVE, - m_activity.getString( R.string.button_html ), - lstnr ); + m_activity.getString( R.string.button_ok ), lstnr ); + ad.setButton( AlertDialog.BUTTON_NEGATIVE, + m_activity.getString( R.string.button_ok ), lstnr ); break; } } @@ -171,16 +173,16 @@ public class DlgDelegate { } } - public void showConfirmThen( String msg, DialogInterface.OnClickListener then ) + public void showConfirmThen( String msg, int callbackID ) { m_msg = msg; - m_then = then; + m_cbckID = callbackID; m_activity.showDialog( CONFIRM_THEN ); } - public void showTextOrHtmlThen( TextOrHtmlClicked txtOrHtml ) + public void showTextOrHtmlThen( int callbackID ) { - m_txt_or_html = txtOrHtml; + m_cbckID = callbackID; m_activity.showDialog( TEXT_OR_HTML_THEN ); } @@ -284,19 +286,25 @@ public class DlgDelegate { private Dialog createHtmlThenDialog() { + DialogInterface.OnClickListener lstnr = + new DialogInterface.OnClickListener() { + public void onClick( DialogInterface dlg, int button ) { + boolean cancelled = + button == DialogInterface.BUTTON_NEGATIVE; + m_clickCallback.dlgButtonClicked( m_cbckID, cancelled ); + } + }; return new AlertDialog.Builder( m_activity ) .setTitle( R.string.query_title ) .setMessage( R.string.text_or_html ) - .setPositiveButton( R.string.button_text, null ) // will change - .setNegativeButton( R.string.button_html, null ) + .setPositiveButton( R.string.button_text, lstnr ) + .setNegativeButton( R.string.button_html, lstnr ) .create(); } private Dialog createDictGoneDialog() { - Utils.logf( "DlgDelegate.createDictGoneDialog() called" ); - Dialog dialog; - dialog = new AlertDialog.Builder( m_activity ) + Dialog dialog = new AlertDialog.Builder( m_activity ) .setTitle( R.string.no_dict_title ) .setMessage( R.string.no_dict_finish ) .setPositiveButton( R.string.button_close_game, null ) diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java index b007ee2ae..f51a684e7 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java @@ -644,6 +644,9 @@ public class GameConfig extends XWActivity { Spinner dictsSpinner = (Spinner)dialog.findViewById( R.id.dict_spinner ); + String fmt = getString( R.string.dicts_list_promptf ); + String lang = DictLangCache.getLangName( this, m_gi.dictLang ); + dictsSpinner.setPrompt(String.format( fmt, lang ) ); OnItemSelectedListener onSel = new OnItemSelectedListener() { diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java index 4eeb5822a..f6a819018 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java @@ -461,21 +461,6 @@ public class GameUtils { } } - public static void launchInviteActivity( final XWActivity activity, - final String room, - final int lang, - final int nPlayers ) - { - DlgDelegate.TextOrHtmlClicked cb = - new DlgDelegate.TextOrHtmlClicked() { - public void clicked( boolean choseText ) { - launchInviteActivity( activity, choseText, room, - lang, nPlayers ); - } - }; - activity.showTextOrHtmlThen( cb ); - } - public static boolean gameDictsHere( Context context, long rowid ) { return gameDictsHere( context, rowid, null, null ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GamesList.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GamesList.java index e91a13658..0320ea5f3 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GamesList.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GamesList.java @@ -63,6 +63,11 @@ public class GamesList extends XWListActivity private static final String SAVE_ROWID = "SAVE_ROWID"; + private static final int NEW_NET_GAME_ACTION = 1; + private static final int RESET_GAME_ACTION = 2; + private static final int DELETE_GAME_ACTION = 3; + private static final int DELETE_ALL_ACTION = 4; + private GameListAdapter m_adapter; private String m_missingDict; private Handler m_handler; @@ -72,6 +77,7 @@ public class GamesList extends XWListActivity private int m_missingDictLang; private long m_rowid; private String m_nameField; + private NetLaunchInfo m_netLaunchInfo; @Override protected Dialog onCreateDialog( int id ) @@ -124,7 +130,7 @@ public class GamesList extends XWListActivity ab.setNeutralButton( R.string.button_substdict, lstnr ); } dialog = ab.create(); - setRemoveOnDismiss( dialog, id ); + Utils.setRemoveOnDismiss( this, dialog, id ); break; case SHOW_SUBST: m_sameLangDicts = @@ -334,12 +340,16 @@ public class GamesList extends XWListActivity { super.onSaveInstanceState( outState ); outState.putLong( SAVE_ROWID, m_rowid ); + if ( null != m_netLaunchInfo ) { + m_netLaunchInfo.putSelf( outState ); + } } private void getBundledData( Bundle bundle ) { if ( null != bundle ) { m_rowid = bundle.getLong( SAVE_ROWID ); + m_netLaunchInfo = new NetLaunchInfo( bundle ); } } @@ -393,6 +403,34 @@ public class GamesList extends XWListActivity onContentChanged(); } + // DlgDelegate.DlgClickNotify interface + public void dlgButtonClicked( int id, boolean cancelled ) + { + if ( !cancelled ) { + switch( id ) { + case NEW_NET_GAME_ACTION: + long rowid = GameUtils.makeNewNetGame( this, m_netLaunchInfo ); + GameUtils.launchGame( this, rowid, true ); + break; + case RESET_GAME_ACTION: + GameUtils.resetGame( this, m_rowid ); + break; + case DELETE_GAME_ACTION: + GameUtils.deleteGame( this, m_rowid, true ); + break; + case DELETE_ALL_ACTION: + long[] games = DBUtils.gamesList( this ); + for ( int ii = games.length - 1; ii >= 0; --ii ) { + GameUtils.deleteGame( this, games[ii], ii == 0 ); + m_adapter.inval( games[ii] ); + } + break; + default: + Assert.fail(); + } + } + } + public void itemClicked( long rowid ) { // We need a way to let the user get back to the basic-config @@ -466,19 +504,9 @@ public class GamesList extends XWListActivity break; case R.id.gamel_menu_delete_all: - final long[] games = DBUtils.gamesList( this ); - if ( games.length > 0 ) { - DialogInterface.OnClickListener lstnr = - new DialogInterface.OnClickListener() { - public void onClick( DialogInterface dlg, int item ) { - for ( int ii = games.length - 1; ii >= 0; --ii ) { - GameUtils.deleteGame( GamesList.this, games[ii], - ii == 0 ); - m_adapter.inval( games[ii] ); - } - } - }; - showConfirmThen( R.string.confirm_delete_all, lstnr ); + if ( DBUtils.gamesList( this ).length > 0 ) { + showConfirmThen( R.string.confirm_delete_all, + DELETE_ALL_ACTION ); } handled = true; break; @@ -525,22 +553,14 @@ public class GamesList extends XWListActivity final long rowid = DBUtils.gamesList( this )[position]; if ( R.id.list_item_delete == menuID ) { - lstnr = new DialogInterface.OnClickListener() { - public void onClick( DialogInterface dlg, int ii ) { - GameUtils.deleteGame( GamesList.this, rowid, true ); - } - }; - showConfirmThen( R.string.confirm_delete, lstnr ); + m_rowid = rowid; + showConfirmThen( R.string.confirm_delete, DELETE_GAME_ACTION ); } else { if ( checkWarnNoDict( rowid ) ) { switch ( menuID ) { case R.id.list_item_reset: - lstnr = new DialogInterface.OnClickListener() { - public void onClick( DialogInterface dlg, int ii ) { - GameUtils.resetGame( GamesList.this, rowid ); - } - }; - showConfirmThen( R.string.confirm_reset, lstnr ); + m_rowid = rowid; + showConfirmThen( R.string.confirm_reset, RESET_GAME_ACTION ); break; case R.id.list_item_config: GameUtils.doConfig( this, rowid, GameConfig.class ); @@ -656,7 +676,7 @@ public class GamesList extends XWListActivity startActivity( new Intent( this, NewGameActivity.class ) ); } - private void startNewNetGame( final NetLaunchInfo info ) + private void startNewNetGame( NetLaunchInfo info ) { long rowid = DBUtils.getRowIDForOpen( this, info.room, info.lang, info.nPlayers ); @@ -665,19 +685,10 @@ public class GamesList extends XWListActivity rowid = GameUtils.makeNewNetGame( this, info ); GameUtils.launchGame( this, rowid, true ); } else { - DialogInterface.OnClickListener then = - new DialogInterface.OnClickListener() { - public void onClick( DialogInterface dlg, - int ii ) { - long rowid = GameUtils. - makeNewNetGame( GamesList.this, info ); - GameUtils.launchGame( GamesList.this, - rowid, true ); - } - }; String fmt = getString( R.string.dup_game_queryf ); String msg = String.format( fmt, info.room ); - showConfirmThen( msg, then ); + m_netLaunchInfo = info; + showConfirmThen( msg, NEW_NET_GAME_ACTION ); } } // startNewNetGame diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/NetLaunchInfo.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/NetLaunchInfo.java index 83619ac0a..ce8499a7f 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/NetLaunchInfo.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/NetLaunchInfo.java @@ -23,6 +23,7 @@ package org.eehouse.android.xw4; import android.content.Context; import android.net.Uri; import android.net.Uri.Builder; +import android.os.Bundle; import java.net.URLEncoder; import org.eehouse.android.xw4.jni.CommonPrefs; @@ -33,8 +34,33 @@ public class NetLaunchInfo { public int lang; public int nPlayers; + private static final String LANG = "netlaunchinfo_lang"; + private static final String ROOM = "netlaunchinfo_room"; + private static final String NPLAYERS = "netlaunchinfo_nplayers"; + private static final String VALID = "netlaunchinfo_valid"; + private boolean m_valid; + public void putSelf( Bundle bundle ) + { + bundle.putInt( LANG, lang ); + bundle.putString( ROOM, room ); + bundle.putInt( NPLAYERS, nPlayers ); + bundle.putBoolean( VALID, m_valid ); + Utils.logf( "bundling NetLaunchInfo: %d, %s, %d, %b", + lang, room, nPlayers, m_valid ); + } + + public NetLaunchInfo( Bundle bundle ) + { + lang = bundle.getInt( LANG ); + room = bundle.getString( ROOM ); + nPlayers = bundle.getInt( NPLAYERS ); + m_valid = bundle.getBoolean( VALID ); + Utils.logf( "unbundled NetLaunchInfo: %d, %s, %d, %b", + lang, room, nPlayers, m_valid ); + } + public static Uri makeLaunchUri( Context context, String room, int lang, int nPlayers ) { diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/NewGameActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/NewGameActivity.java index 1e8fdeaef..067ae0896 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/NewGameActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/NewGameActivity.java @@ -29,6 +29,7 @@ import android.view.View; import android.widget.Button; import android.widget.TextView; import java.util.Random; +import junit.framework.Assert; import org.eehouse.android.xw4.jni.CurGameInfo; import org.eehouse.android.xw4.jni.CommonPrefs; @@ -38,6 +39,8 @@ import org.eehouse.android.xw4.jni.XwJNI; public class NewGameActivity extends XWActivity { + private static final int NEW_GAME_ACTION = 1; + @Override protected void onCreate(Bundle savedInstanceState) { @@ -84,15 +87,22 @@ public class NewGameActivity extends XWActivity { } + public void dlgButtonClicked( int id, boolean cancelled ) + { + switch( id ) { + case NEW_GAME_ACTION: + makeNewGame( true, true, !cancelled ); + break; + default: + Assert.fail(); + } + } + private void makeNewGame( boolean networked, boolean launch ) { if ( launch && networked ) { // Let 'em cancel before we make the game - showTextOrHtmlThen( new DlgDelegate.TextOrHtmlClicked() { - public void clicked( boolean choseText ) { - makeNewGame( true, true, choseText ); - } - } ); + showTextOrHtmlThen( NEW_GAME_ACTION ); } else { makeNewGame( networked, launch, false ); } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/Utils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/Utils.java index ec785a166..5edf3f811 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/Utils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/Utils.java @@ -22,14 +22,15 @@ package org.eehouse.android.xw4; import android.util.Log; import java.lang.Thread; -import android.widget.Toast; +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.widget.CheckBox; -import android.app.Activity; -import android.app.Dialog; +import android.widget.Toast; import android.widget.EditText; import android.widget.TextView; import android.view.LayoutInflater; @@ -105,6 +106,16 @@ public class Utils { Toast.makeText( context, text, Toast.LENGTH_SHORT).show(); } + public static void setRemoveOnDismiss( final Activity activity, + Dialog dialog, final int id ) + { + dialog.setOnDismissListener( new DialogInterface.OnDismissListener() { + public void onDismiss( DialogInterface di ) { + activity.removeDialog( id ); + } + } ); + } + public static View inflate( Context context, int layoutId ) { LayoutInflater factory = LayoutInflater.from( context ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/XWActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/XWActivity.java index d094a9adf..212c818e2 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/XWActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/XWActivity.java @@ -32,7 +32,8 @@ import android.os.Bundle; import org.eehouse.android.xw4.jni.CommonPrefs; -public class XWActivity extends Activity { +public class XWActivity extends Activity + implements DlgDelegate.DlgClickNotify { private DlgDelegate m_delegate; @@ -41,7 +42,7 @@ public class XWActivity extends Activity { { Utils.logf( "%s.onCreate(this=%H)", getClass().getName(), this ); super.onCreate( savedInstanceState ); - m_delegate = new DlgDelegate( this ); + m_delegate = new DlgDelegate( this, this, savedInstanceState ); } @Override @@ -82,6 +83,13 @@ public class XWActivity extends Activity { super.onDestroy(); } + @Override + protected void onSaveInstanceState( Bundle outState ) + { + super.onSaveInstanceState( outState ); + m_delegate.onSaveInstanceState( outState ); + } + @Override protected Dialog onCreateDialog( int id ) { @@ -93,11 +101,6 @@ public class XWActivity extends Activity { return dialog; } - protected void setRemoveOnDismiss( Dialog dialog, int id ) - { - m_delegate.setRemoveOnDismiss( dialog, id ); - } - @Override protected void onPrepareDialog( int id, Dialog dialog ) { @@ -128,19 +131,25 @@ public class XWActivity extends Activity { m_delegate.showDictGoneFinish(); } - protected void showConfirmThen( int msgID, - DialogInterface.OnClickListener action ) + protected void showConfirmThen( int msgID, int action ) { m_delegate.showConfirmThen( getString(msgID), action ); } - public void showTextOrHtmlThen( DlgDelegate.TextOrHtmlClicked txtOrHtml ) + public void showTextOrHtmlThen( int action ) { - m_delegate.showTextOrHtmlThen( txtOrHtml ); + m_delegate.showTextOrHtmlThen( action ); } protected void doSyncMenuitem() { m_delegate.doSyncMenuitem(); } + + // DlgDelegate.DlgClickNotify interface + public void dlgButtonClicked( int id, boolean cancelled ) + { + Assert.fail(); + } + } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/XWListActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/XWListActivity.java index bb1206eff..f5cfd781a 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/XWListActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/XWListActivity.java @@ -25,9 +25,13 @@ import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; +import junit.framework.Assert; + import org.eehouse.android.xw4.jni.CommonPrefs; -public class XWListActivity extends ListActivity { +public class XWListActivity extends ListActivity + implements DlgDelegate.DlgClickNotify { + private DlgDelegate m_delegate; @Override @@ -35,7 +39,7 @@ public class XWListActivity extends ListActivity { { Utils.logf( "%s.onCreate(this=%H)", getClass().getName(), this ); super.onCreate( savedInstanceState ); - m_delegate = new DlgDelegate( this ); + m_delegate = new DlgDelegate( this, this, savedInstanceState ); } @Override @@ -76,6 +80,13 @@ public class XWListActivity extends ListActivity { super.onDestroy(); } + @Override + protected void onSaveInstanceState( Bundle outState ) + { + super.onSaveInstanceState( outState ); + m_delegate.onSaveInstanceState( outState ); + } + @Override protected Dialog onCreateDialog( final int id ) { @@ -98,11 +109,6 @@ public class XWListActivity extends ListActivity { return dialog; } - protected void setRemoveOnDismiss( Dialog dialog, int id ) - { - m_delegate.setRemoveOnDismiss( dialog, id ); - } - @Override protected void onPrepareDialog( int id, Dialog dialog ) { @@ -132,16 +138,14 @@ public class XWListActivity extends ListActivity { m_delegate.showOKOnlyDialog( msgID ); } - protected void showConfirmThen( String msg, - DialogInterface.OnClickListener action ) + protected void showConfirmThen( String msg, int action ) { m_delegate.showConfirmThen( msg, action ); } - protected void showConfirmThen( int msgID, - DialogInterface.OnClickListener action ) + protected void showConfirmThen( int msg, int action ) { - showConfirmThen( getString(msgID), action ); + m_delegate.showConfirmThen( getString(msg), action ); } protected void doSyncMenuitem() @@ -149,4 +153,10 @@ public class XWListActivity extends ListActivity { m_delegate.doSyncMenuitem(); } + // DlgDelegate.DlgClickNotify interface + public void dlgButtonClicked( int id, boolean cancelled ) + { + Assert.fail(); + } + } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/GameSummary.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/GameSummary.java index 6a2dee187..d6953d405 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/GameSummary.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/GameSummary.java @@ -118,10 +118,18 @@ public class GameSummary { { String result = null; if ( isRelayGame() ) { + Assert.assertTrue( CommsAddrRec.CommsConnType.COMMS_CONN_RELAY == conType ); - String fmt = m_context.getString( R.string.summary_fmt_relay ); - result = String.format( fmt, roomName ); + int fmtID; + if ( null == relayID || 0 == relayID.length() ) { + fmtID = R.string.summary_relay_conff; + } else if ( anyMissing() ) { + fmtID = R.string.summary_relay_waitf; + } else { + fmtID = R.string.summary_relay_connf; + } + result = String.format( m_context.getString(fmtID), roomName ); } return result; } @@ -144,6 +152,18 @@ public class GameSummary { return result; } + private boolean anyMissing() + { + boolean missing = false; + for ( int ii = 0; ii < nPlayers; ++ii ) { + if ( !isLocal(ii) && (0 != ((1 << ii) & missingPlayers) ) ) { + missing = true; + break; + } + } + return missing; + } + public int giflags() { int result; if ( null == m_gi ) {