diff --git a/xwords4/android/XWords4/jni/Android.mk b/xwords4/android/XWords4/jni/Android.mk index 057f89440..25e123332 100644 --- a/xwords4/android/XWords4/jni/Android.mk +++ b/xwords4/android/XWords4/jni/Android.mk @@ -10,7 +10,7 @@ local_C_INCLUDES+= \ local_LDLIBS += -llog -# local_DEBUG = -DMEM_DEBUG -DDEBUG -DENABLE_LOGGING +local_DEBUG = -DMEM_DEBUG -DDEBUG -DENABLE_LOGGING local_DEFINES += \ $(local_DEBUG) \ -DXWFEATURE_RELAY \ diff --git a/xwords4/android/XWords4/jni/xwjni.c b/xwords4/android/XWords4/jni/xwjni.c index 28f3a5f4c..26f4c4f2e 100644 --- a/xwords4/android/XWords4/jni/xwjni.c +++ b/xwords4/android/XWords4/jni/xwjni.c @@ -82,6 +82,8 @@ makeGI( MPFORMAL JNIEnv* env, jobject j_gi ) lp->name = copyString( mpool, buf ); getString( env, jlp, "password", buf, VSIZE(buf) ); lp->password = copyString( mpool, buf ); + getString( env, jlp, "dictName", buf, VSIZE(buf) ); + lp->dictName = copyString( mpool, buf ); lp->secondsUsed = 0; @@ -129,6 +131,7 @@ setJGI( JNIEnv* env, jobject jgi, const CurGameInfo* gi ) setBool( env, jlp, "isLocal", lp->isLocal ); setString( env, jlp, "name", lp->name ); setString( env, jlp, "password", lp->password ); + setString( env, jlp, "dictName", lp->dictName ); setInt( env, jlp, "secondsUsed", lp->secondsUsed ); (*env)->DeleteLocalRef( env, jlp ); diff --git a/xwords4/android/XWords4/res/layout/game_config.xml b/xwords4/android/XWords4/res/layout/game_config.xml index aeb62ceac..b7d0c3dbe 100644 --- a/xwords4/android/XWords4/res/layout/game_config.xml +++ b/xwords4/android/XWords4/res/layout/game_config.xml @@ -78,14 +78,14 @@ - + + + + Create game Edit game Crosswords - Dictionaries (language/wordcount) + Dictionaries (wordcount) + Languages (based on installed + dictionaries) + Game language Game %s settings %s settings (networked) @@ -164,6 +167,7 @@ Details Dictionary + Dictionary (in %s) Device role Connection Connection (via internet) diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictLangCache.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictLangCache.java index 45935e866..9b43b03a2 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictLangCache.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictLangCache.java @@ -24,6 +24,8 @@ import android.content.Context; import android.content.res.Resources; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.Arrays; import org.eehouse.android.xw4.jni.JNIUtilsImpl; import org.eehouse.android.xw4.jni.XwJNI; @@ -33,6 +35,7 @@ public class DictLangCache { private static final HashMap s_nameToLang = new HashMap(); private static String[] s_langNames; + private static String[] s_langNamesPresent; public static String annotatedDictName( Context context, String name ) { @@ -72,7 +75,7 @@ public class DictLangCache { int count = 0; String[] dicts = GameUtils.dictList( context ); for ( String dict : dicts ) { - if ( code == getLangCode( context, dict ) ) { + if ( code == getDictLangCode( context, dict ) ) { ++count; } } @@ -94,7 +97,9 @@ public class DictLangCache { al.add( dict ); } } - return al.toArray( new String[al.size()] ); + String[] result = al.toArray( new String[al.size()] ); + Arrays.sort( result ); + return result; } public static String[] getHaveLang( Context context, int code ) @@ -113,14 +118,27 @@ public class DictLangCache { return nameWithCount.substring( 0, indx ); } - public static int getLangCode( Context context, String name ) + public static int getDictLangCode( Context context, String dict ) { - return getInfo( context, name ).langCode; + return getInfo( context, dict ).langCode; + } + + public static int getLangLangCode( Context context, String lang ) + { + int code = 0; + String[] namesArray = getNamesArray( context ); + for ( int ii = 0; ii < namesArray.length; ++ii ) { + if ( namesArray[ii].equals( lang ) ) { + code = ii; + break; + } + } + return code; } public static String getLangName( Context context, String name ) { - int code = getLangCode( context, name ); + int code = getDictLangCode( context, name ); return getLangName( context, code ); } @@ -129,6 +147,16 @@ public class DictLangCache { s_nameToLang.remove( name ); } + public static String[] listLangs( Context context, final String[] names ) + { + HashSet langs = new HashSet(); + for ( String name:names ) { + langs.add( getLangName( context, name ) ); + } + String[] result = new String[langs.size()]; + return langs.toArray( result ); + } + private static String[] getNamesArray( Context context ) { if ( null == s_langNames ) { 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 696e1a348..19cca53d2 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java @@ -26,6 +26,7 @@ import android.net.Uri; import android.os.Bundle; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; @@ -90,11 +91,11 @@ public class GameConfig extends XWActivity // private Spinner m_roleSpinner; // private Spinner m_connectSpinner; private Spinner m_phoniesSpinner; - private Spinner m_dictSpinner; + private Spinner m_langSpinner; private Spinner m_smartnessSpinner; - private String[] m_dictItems; - private String[] m_dicts; - private int m_browsePosition; + private String[] m_langs; + // private String[] m_dicts; + private int m_langsBrowsePosition; private LinearLayout m_playerLayout; private CommsAddrRec m_carOrig; private CommsAddrRec m_car; @@ -106,7 +107,7 @@ public class GameConfig extends XWActivity private String[] m_connStrings; private static final int[] s_disabledWhenLocked = { R.id.juggle_players ,R.id.add_player - ,R.id.dict_spinner + ,R.id.lang_spinner ,R.id.join_public_room_check ,R.id.room_edit ,R.id.advertise_new_room_check @@ -297,6 +298,14 @@ public class GameConfig extends XWActivity Utils.setText( dialog, R.id.player_name_edit, lp.name ); Utils.setText( dialog, R.id.password_edit, lp.password ); + // Dicts spinner with label + String langName = DictLangCache.getLangName( this, m_gi.dictLang ); + String label = String.format( getString( R.string.dict_lang_labelf ), + langName ); + TextView text = (TextView)dialog.findViewById( R.id.dict_label ); + text.setText( label ); + configDictSpinner( dialog, lp ); + final View localSet = dialog.findViewById( R.id.local_player_set ); CheckBox check = (CheckBox) @@ -338,6 +347,11 @@ public class GameConfig extends XWActivity LocalPlayer lp = m_gi.players[m_whichPlayer]; lp.name = Utils.getText( dialog, R.id.player_name_edit ); lp.password = Utils.getText( dialog, R.id.password_edit ); + Spinner spinner = + (Spinner)((Dialog)di).findViewById( R.id.dict_spinner ); + int position = spinner.getSelectedItemPosition(); + lp.dictName = DictLangCache.getHaveLang( this, m_gi.dictLang )[position]; + Utils.logf( "reading name via position %d: %s", position, lp.dictName ); lp.setIsRobot( Utils.getChecked( dialog, R.id.robot_check ) ); lp.isLocal = !Utils.getChecked( dialog, R.id.remote_check ); @@ -376,7 +390,7 @@ public class GameConfig extends XWActivity m_playButton.setOnClickListener( this ); m_playerLayout = (LinearLayout)findViewById( R.id.player_list ); - m_dictSpinner = (Spinner)findViewById( R.id.dict_spinner ); + m_langSpinner = (Spinner)findViewById( R.id.lang_spinner ); m_phoniesSpinner = (Spinner)findViewById( R.id.phonies_spinner ); m_smartnessSpinner = (Spinner)findViewById( R.id.smart_robot ); @@ -409,9 +423,9 @@ public class GameConfig extends XWActivity handleLockedChange(); } - int curSel = listAvailableDicts( m_giOrig.dictName ); + int curSel = listAvailableLangs( m_giOrig.dictName ); m_giOrig.dictLang = - DictLangCache.getLangCode( this, + DictLangCache.getDictLangCode( this, GameUtils.dictList( this )[curSel] ); m_gi = new CurGameInfo( m_giOrig ); @@ -453,8 +467,7 @@ public class GameConfig extends XWActivity } loadPlayers(); - - configDictSpinner(); + configLangSpinner(); m_phoniesSpinner.setSelection( m_gi.phoniesAction.ordinal() ); @@ -620,62 +633,109 @@ public class GameConfig extends XWActivity adjustPlayersLabel(); } // loadPlayers - private int listAvailableDicts( String curDict ) + private String[] buildListWithBrowse( String[] input ) { - int curSel = -1; - - String[] list = GameUtils.dictList( this ); - - m_browsePosition = list.length; - m_dictItems = new String[m_browsePosition+1]; - m_dictItems[m_browsePosition] = getString( R.string.download_dicts ); - m_dicts = new String[m_browsePosition]; + Arrays.sort( input ); + int browsePosn = input.length; + String[] result = new String[browsePosn+1]; + result[browsePosn] = getString( R.string.download_dicts ); - for ( int ii = 0; ii < m_browsePosition; ++ii ) { - String dict = list[ii]; - m_dicts[ii] = dict; - m_dictItems[ii] = DictLangCache.annotatedDictName( this, dict ); - if ( dict.equals( curDict ) ) { - curSel = ii; - } + for ( int ii = 0; ii < browsePosn; ++ii ) { + String lang = input[ii]; + result[ii] = lang; } - - return curSel; + return result; } - private void configDictSpinner() + private int listAvailableLangs( String curDict ) { - int curSel = listAvailableDicts( m_gi.dictName ); + String[] langs = + DictLangCache.listLangs( this, GameUtils.dictList( this ) ); + String curLang = DictLangCache.getLangName( this, curDict ); + m_langs = buildListWithBrowse( langs ); + m_langsBrowsePosition = m_langs.length - 1; + return Arrays.binarySearch( m_langs, curLang ); + } // listAvailableLangs + + private void configDictSpinner( final Dialog dialog, final LocalPlayer lp ) + { + String[] tmpDicts = + DictLangCache.getHaveLang( this, m_gi.dictLang ); + final String[] dicts = buildListWithBrowse( tmpDicts ); + Spinner dictsSpinner = + (Spinner)dialog.findViewById( R.id.dict_spinner ); + int curSel = -1; + if ( null != lp.dictName ) { + curSel = Arrays.binarySearch( dicts, lp.dictName ); + } + + OnItemSelectedListener onSel = + new OnItemSelectedListener() { + @Override + public void onItemSelected( AdapterView parentView, + View selectedItemView, + int position, long id ) { + if ( position == dicts.length - 1 ) { + Utils.logf( "posn=%d; starting activity", position ); + startActivity( Utils.mkDownloadActivity(GameConfig.this, + m_gi.dictLang ) ); + } else { + // lp.dictName = dicts[position]; + // Utils.logf( "set lp.dictName: %s", lp.dictName ); + } + } + + @Override + public void onNothingSelected(AdapterView parentView) {} + }; + + configSpinnerWDownload( dictsSpinner, dicts, curSel, onSel ); + } + + private void configLangSpinner() + { + OnItemSelectedListener onSel = + new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parentView, + View selectedItemView, + int position, long id ) { + if ( position == m_langsBrowsePosition ) { + Utils.logf( "configLangSpinner: position=%d; starting download", position ); + startActivity( Utils.mkDownloadActivity(GameConfig.this) ); + } else { + m_gi.dictLang = + DictLangCache.getLangLangCode( GameConfig.this, + m_langs[position] ); + } + } + + @Override + public void onNothingSelected(AdapterView parentView) {} + }; + configSpinnerWDownload( m_langSpinner, m_langs, + listAvailableLangs( m_gi.dictName ), + onSel ); + } + + private void configSpinnerWDownload( Spinner spinner, String[] texts, + int curSel, + OnItemSelectedListener onSel ) + { ArrayAdapter adapter = new ArrayAdapter( this, android.R.layout.simple_spinner_item, - m_dictItems ); + texts ); int resID = android.R.layout.simple_spinner_dropdown_item; adapter.setDropDownViewResource( resID ); - m_dictSpinner.setAdapter( adapter ); + spinner.setAdapter( adapter ); if ( curSel >= 0 ) { - m_dictSpinner.setSelection( curSel ); + Utils.logf( "setting selection: %d", curSel ); + spinner.setSelection( curSel ); } - m_dictSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parentView, - View selectedItemView, - int position, long id ) { - if ( position == m_browsePosition ) { - startActivity( Utils.mkDownloadActivity(GameConfig.this) ); - } else { - m_gi.dictName = m_dicts[position]; - Utils.logf( "assigned dictName: " + m_gi.dictName ); - m_gi.dictLang = DictLangCache.getLangCode( GameConfig.this, - m_gi.dictName ); - } - } - - @Override - public void onNothingSelected(AdapterView parentView) {} - }); + spinner.setOnItemSelectedListener( onSel ); } private void setSmartnessSpinner() 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 8cbd1ed9a..2ba47e7fe 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/Utils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/Utils.java @@ -109,9 +109,11 @@ public class Utils { String dict, int lang ) { String dict_url = CommonPrefs.getDefaultDictURL( context ); + if ( 0 != lang ) { + dict_url += "/" + DictLangCache.getLangName( context, lang ); + } if ( null != dict ) { - dict_url += "/" + DictLangCache.getLangName( context, lang ) - + "/" + dict + XWConstants.DICT_EXTN; + dict_url += "/" + dict + XWConstants.DICT_EXTN; } Uri uri = Uri.parse( dict_url ); Intent intent = new Intent( Intent.ACTION_VIEW, uri ); @@ -124,6 +126,11 @@ public class Utils { return mkDownloadActivity( context, null, 0 ); } + public static Intent mkDownloadActivity( Context context, int lang ) + { + return mkDownloadActivity( context, null, lang ); + } + public static void setChecked( Activity activity, int id, boolean value ) { CheckBox cbx = (CheckBox)activity.findViewById( id ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/CurGameInfo.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/CurGameInfo.java index f84967823..e992cc54d 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/CurGameInfo.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/CurGameInfo.java @@ -73,7 +73,7 @@ public class CurGameInfo { serverRole = isNetworked ? DeviceRole.SERVER_ISCLIENT : DeviceRole.SERVER_STANDALONE; dictName = CommonPrefs.getDefaultDict( context ); - dictLang = DictLangCache.getLangCode( context, dictName ); + dictLang = DictLangCache.getDictLangCode( context, dictName ); hintsNotAllowed = !CommonPrefs.getDefaultHintsAllowed( context ); phoniesAction = CommonPrefs.getDefaultPhonies( context ); timerEnabled = CommonPrefs.getDefaultTimerEnabled( context ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/LocalPlayer.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/LocalPlayer.java index 9dce35871..62a6951e1 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/LocalPlayer.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/LocalPlayer.java @@ -27,6 +27,7 @@ import junit.framework.Assert; public class LocalPlayer { public String name; public String password; + public String dictName; public int secondsUsed; public int robotIQ; public boolean isLocal; @@ -50,6 +51,9 @@ public class LocalPlayer { if ( null != src.password ) { password = new String(src.password); } + if ( null != src.dictName ) { + dictName = new String(src.dictName); + } secondsUsed = src.secondsUsed; }