From b0cef99507b0d438e4a77ca43c5f46b7bb8d8871 Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 1 Feb 2017 20:36:59 -0800 Subject: [PATCH] preserve wordlist selection and remote info wordlist browser selection and downloaded info about downloadable wordlists didn't survive rotation. They do now, the latter as a huge serialized array. To make selection work I save the keySet() of a mapping of selected names to the views that represent them. Now the presence of a key, even if the value is (temporarily) null, signals that something's selected. --- .../eehouse/android/xw4/DictsDelegate.java | 190 ++++++++++-------- .../android/xw4/GamesListDelegate.java | 3 +- 2 files changed, 106 insertions(+), 87 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DictsDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DictsDelegate.java index eab9579b0..c3d4390c1 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DictsDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DictsDelegate.java @@ -60,6 +60,8 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import java.io.Serializable; + import java.net.HttpURLConnection; import java.util.ArrayList; import java.util.Arrays; @@ -76,6 +78,10 @@ public class DictsDelegate extends ListDelegateBase DownloadFinishedListener, XWListItem.ExpandedListener { private static final String TAG = DictsDelegate.class.getSimpleName(); + private static final String REMOTE_SHOW_KEY = "REMOTE_SHOW_KEY"; + private static final String REMOTE_INFO_KEY = "REMOTE_INFO_KEY"; + private static final String SEL_DICTS_KEY = "SEL_DICTS_KEY"; + protected static final String DICT_SHOWREMOTE = "do_launch"; protected static final String DICT_LANG_EXTRA = "use_lang"; protected static final String DICT_NAME_EXTRA = "use_dict"; @@ -96,7 +102,8 @@ public class DictsDelegate extends ListDelegateBase private CheckBox m_checkbox; private String[] m_locNames; private String m_finishOnName; - private Map m_selDicts; + private Map m_selViews; + private Map m_selDicts = new HashMap(); private String m_origTitle; private boolean m_showRemote = false; private String m_filterLang; @@ -153,7 +160,7 @@ public class DictsDelegate extends ListDelegateBase } } - private static class DictInfo implements Comparable { + private static class DictInfo implements Comparable, Serializable { public String m_name; public String m_lang; public int m_nWords; @@ -249,11 +256,11 @@ public class DictsDelegate extends ListDelegateBase } result = item; + String name = null; if ( dataObj instanceof DictAndLoc ) { DictAndLoc dal = (DictAndLoc)dataObj; - String name = dal.name; - item.setText( name ); + name = dal.name; DictLoc loc = dal.loc; item.setComment( m_locNames[loc.ordinal()] ); @@ -262,28 +269,27 @@ public class DictsDelegate extends ListDelegateBase item.setOnClickListener( DictsDelegate.this ); item.setExpandedListener( null ); // item might be reused - // Replace sel entry if present - if ( m_selDicts.containsKey( name ) ) { - m_selDicts.put( name, item ); - item.setSelected( true ); - } } else if ( dataObj instanceof DictInfo ) { DictInfo info = (DictInfo)dataObj; - String name = info.m_name; - item.setText( name ); + name = info.m_name; + item.setCached( info ); item.setExpandedListener( DictsDelegate.this ); item.setExpanded( m_expandedItems.contains( info ) ); item.setComment( m_onServerStr ); - if ( m_selDicts.containsKey( name ) ) { - m_selDicts.put( name, item ); - item.setSelected( true ); - } } else { Assert.fail(); } + + item.setText( name ); + + boolean selected = m_selDicts.containsKey( name ); + if ( selected ) { + m_selViews.put( name, item ); + } + item.setSelected( selected ); } return result; } @@ -362,10 +368,10 @@ public class DictsDelegate extends ListDelegateBase DlgID dlgID = DlgID.values()[id]; switch( dlgID ) { case MOVE_DICT: - final XWListItem[] selItems = getSelItems(); + final String[] selNames = getSelNames(); final int[] moveTo = { -1 }; message = getString( R.string.move_dict_fmt, - getJoinedNames( selItems ) ); + getJoinedSelNames(selNames) ); OnClickListener newSelLstnr = new OnClickListener() { @@ -389,7 +395,7 @@ public class DictsDelegate extends ListDelegateBase DictsDelegate self = curThis(); DictLoc toLoc = self.itemToRealLoc( moveTo[0] ); Assert.assertTrue( self == DictsDelegate.this ); - moveDicts( selItems, toLoc ); + moveDicts( selNames, toLoc ); } }; @@ -403,23 +409,22 @@ public class DictsDelegate extends ListDelegateBase break; case SET_DEFAULT: - final XWListItem row = m_selDicts.values().iterator().next(); + final String name = m_selDicts.keySet().iterator().next(); lstnr = new OnClickListener() { public void onClick( DialogInterface dlg, int item ) { DictsDelegate self = curThis(); if ( DialogInterface.BUTTON_NEGATIVE == item || DialogInterface.BUTTON_POSITIVE == item ) { - self.setDefault( row, R.string.key_default_dict, + self.setDefault( name, R.string.key_default_dict, R.string.key_default_robodict ); } if ( DialogInterface.BUTTON_NEGATIVE == item || DialogInterface.BUTTON_NEUTRAL == item ) { - self.setDefault( row, R.string.key_default_robodict, + self.setDefault( name, R.string.key_default_robodict, R.string.key_default_dict ); } } }; - String name = row.getText(); String lang = DictLangCache.getLangName( m_activity, name); lang = xlateLang( lang ); message = getString( R.string.set_default_message_fmt, name, lang ); @@ -479,6 +484,7 @@ public class DictsDelegate extends ListDelegateBase } } + @Override protected void init( Bundle savedInstanceState ) { m_onServerStr = getString( R.string.dict_on_server ); @@ -499,7 +505,8 @@ public class DictsDelegate extends ListDelegateBase m_checkbox = (CheckBox)findViewById( R.id.show_remote ); m_checkbox.setOnClickListener( this ); - mkListAdapter(); + getBundledData( savedInstanceState ); + m_checkbox.setSelected( m_showRemote ); Bundle args = getArguments(); if ( null != args ) { @@ -556,6 +563,23 @@ public class DictsDelegate extends ListDelegateBase super.onStop(); } + @Override + protected void onSaveInstanceState( Bundle outState ) + { + outState.putBoolean( REMOTE_SHOW_KEY, m_showRemote ); + outState.putSerializable( REMOTE_INFO_KEY, m_remoteInfo ); + outState.putSerializable( SEL_DICTS_KEY, (HashMap)m_selDicts ); + } + + private void getBundledData( Bundle sis ) + { + if ( null != sis ) { + m_showRemote = sis.getBoolean( REMOTE_SHOW_KEY, false ); + m_remoteInfo = (HashMap)sis.getSerializable( REMOTE_INFO_KEY ); + m_selDicts = (HashMap)sis.getSerializable( SEL_DICTS_KEY ); + } + } + public void onClick( View view ) { if ( view == m_checkbox ) { @@ -631,13 +655,12 @@ public class DictsDelegate extends ListDelegateBase Uri[] uris = new Uri[countNeedDownload()]; String[] names = new String[uris.length]; int count = 0; - for ( Iterator iter = m_selDicts.values().iterator(); - iter.hasNext(); ) { - XWListItem litm = iter.next(); - Object cached = litm.getCached(); + + for ( Map.Entry entry : m_selDicts.entrySet() ) { + Object cached = entry.getValue(); if ( cached instanceof DictInfo ) { DictInfo info = (DictInfo)cached; - String name = litm.getText(); + String name = entry.getKey(); Uri uri = Utils.makeDictUri( m_activity, info.m_lang, name ); uris[count] = uri; @@ -654,36 +677,38 @@ public class DictsDelegate extends ListDelegateBase return handled; } - private void moveDicts( XWListItem[] selItems, DictLoc toLoc ) + private void moveDicts( String[] selNames, DictLoc toLoc ) { if ( DictUtils.needsStoragePermission( toLoc ) ) { tryGetPerms( Perm.STORAGE, R.string.move_dict_rationale, - Action.MOVE_CONFIRMED, selItems, toLoc ); + Action.MOVE_CONFIRMED, selNames, toLoc ); } else { - moveDictsWithPermission( selItems, toLoc ); + moveDictsWithPermission( selNames, toLoc ); } } private void moveDictsWithPermission( Object[] params ) { - XWListItem[] selItems = (XWListItem[])params[0]; + String[] selNames = (String[])params[0]; DictLoc toLoc = (DictLoc)params[1]; - moveDictsWithPermission( selItems, toLoc ); + moveDictsWithPermission( selNames, toLoc ); } - private void moveDictsWithPermission( XWListItem[] selItems, DictLoc toLoc ) + private void moveDictsWithPermission( String[] selNames, DictLoc toLoc ) { - for ( XWListItem selItem : selItems ) { - DictLoc fromLoc = (DictLoc)selItem.getCached(); - String name = selItem.getText(); + for ( String name : selNames ) { + DictLoc fromLoc = (DictLoc)m_selDicts.get( name ); if ( fromLoc == toLoc ) { DbgUtils.logw( TAG, "not moving %s: same loc", name ); } else if ( DictUtils.moveDict( m_activity, name, fromLoc, toLoc ) ) { - selItem.setComment( m_locNames[toLoc.ordinal()] ); - selItem.setCached( toLoc ); - selItem.invalidate(); + if ( m_selViews.containsKey( name ) ) { + XWListItem selItem = m_selViews.get( name ); + selItem.setComment( m_locNames[toLoc.ordinal()] ); + selItem.setCached( toLoc ); + selItem.invalidate(); + } DBUtils.dictsMoveInfo( m_activity, name, fromLoc, toLoc ); } else { @@ -691,7 +716,6 @@ public class DictsDelegate extends ListDelegateBase DbgUtils.logw( TAG, "moveDict(%s) failed", name ); } } - } private void switchShowingRemote( boolean showRemote ) @@ -712,10 +736,9 @@ public class DictsDelegate extends ListDelegateBase private int countNeedDownload() { int result = 0; - for ( Iterator iter = m_selDicts.values().iterator(); + for ( Iterator iter = m_selDicts.values().iterator(); iter.hasNext(); ) { - XWListItem litm = iter.next(); - Object obj = litm.getCached(); + Object obj = iter.next(); if ( obj instanceof DictInfo ) { ++result; } @@ -737,9 +760,8 @@ public class DictsDelegate extends ListDelegateBase } } - private void setDefault( XWListItem view, int keyId, int otherKey ) + private void setDefault( String name, int keyId, int otherKey ) { - String name = view.getText(); int langCode = DictLangCache.getDictLangCode( m_activity, name ); String curLangName = XWPrefs.getPrefsString( m_activity, R.string.key_default_language ); int curLangCode = DictLangCache.getLangLangCode( m_activity, curLangName ); @@ -797,9 +819,9 @@ public class DictsDelegate extends ListDelegateBase private boolean selItemsVolatile() { boolean result = 0 < m_selDicts.size(); - for ( Iterator iter = m_selDicts.values().iterator(); + for ( Iterator iter = m_selDicts.values().iterator(); result && iter.hasNext(); ) { - Object obj = iter.next().getCached(); + Object obj = iter.next(); if ( obj instanceof DictLoc ) { DictLoc loc = (DictLoc)obj; if ( loc == DictLoc.BUILT_IN ) { @@ -814,9 +836,9 @@ public class DictsDelegate extends ListDelegateBase private void deleteSelected() { - XWListItem[] items = getSelItems(); + String[] names = getSelNames(); String msg = getQuantityString( R.plurals.confirm_delete_dict_fmt, - items.length, getJoinedNames( items ) ); + names.length, getJoinedSelNames(names) ); // Confirm. And for each dict, warn if (after ALL are deleted) any // game will no longer be openable without downloading. For now @@ -845,8 +867,7 @@ public class DictsDelegate extends ListDelegateBase Map dels = new HashMap(); Set skipLangs = new HashSet(); - for ( XWListItem item : items ) { - String dict = item.getText(); + for ( String dict : m_selDicts.keySet() ) { int langCode = DictLangCache.getDictLangCode( m_activity, dict ); if ( skipLangs.contains( langCode ) ) { continue; @@ -879,7 +900,7 @@ public class DictsDelegate extends ListDelegateBase makeConfirmThenBuilder( msg, Action.DELETE_DICT_ACTION ) .setPosButton( R.string.button_delete ) - .setParams( (Object)items ) + .setParams( (Object)names ) .show(); } // deleteSelected @@ -906,18 +927,18 @@ public class DictsDelegate extends ListDelegateBase { switch( action ) { case DELETE_DICT_ACTION: - XWListItem[] items = (XWListItem[])params[0]; - for ( XWListItem item : items ) { - String name = item.getText(); - DictLoc loc = (DictLoc)item.getCached(); + String[] names = (String[])params[0]; + for ( String name : names ) { + DictLoc loc = (DictLoc)m_selDicts.get( name ); deleteDict( name, loc ); } clearSelections(); + mkListAdapter(); break; case UPDATE_DICTS_ACTION: Uri[] uris = new Uri[m_needUpdates.size()]; - String[] names = new String[uris.length]; + names = new String[uris.length]; int count = 0; for ( Iterator iter = m_needUpdates.keySet().iterator(); iter.hasNext(); ) { @@ -969,7 +990,7 @@ public class DictsDelegate extends ListDelegateBase m_adapter = new DictListAdapter( m_activity ); setListAdapterKeepScroll( m_adapter ); - m_selDicts = new HashMap(); + m_selViews = new HashMap(); } private void saveClosed() @@ -981,50 +1002,45 @@ public class DictsDelegate extends ListDelegateBase private void clearSelections() { if ( 0 < m_selDicts.size() ) { - XWListItem[] items = getSelItems(); - - m_selDicts.clear(); - - for ( XWListItem item : items ) { - item.setSelected( false ); + for ( String name : getSelNames() ) { + if ( m_selViews.containsKey( name ) ) { + XWListItem item = m_selViews.get( name ); + item.setSelected( false ); + } } + m_selDicts.clear(); + m_selViews.clear(); } } - private String getJoinedNames( XWListItem[] items ) + private String[] getSelNames() + { + Set nameSet = m_selDicts.keySet(); + String[] names = nameSet.toArray( new String[nameSet.size()] ); + return names; + } + + private String getJoinedSelNames(String[] names) { - String[] names = new String[items.length]; - int ii = 0; - for ( XWListItem item : items ) { - names[ii++] = item.getText(); - } return TextUtils.join( ", ", names ); } - private XWListItem[] getSelItems() + private String getJoinedSelNames() { - XWListItem[] items = new XWListItem[m_selDicts.size()]; - int indx = 0; - for ( Iterator iter = m_selDicts.values().iterator(); - iter.hasNext(); ) { - items[indx++] = iter.next(); - } - return items; + String[] names = getSelNames(); + return getJoinedSelNames( names ); } - private int[] countSelDicts() { - int[] results = new int[2]; - Assert.assertTrue( 0 == results[0] && 0 == results[1] ); - for ( Iterator iter = m_selDicts.values().iterator(); - iter.hasNext(); ) { - Object obj = iter.next().getCached(); + int[] results = new int[] { 0, 0 }; + for ( Object obj : m_selDicts.values() ) { if ( obj instanceof DictLoc ) { ++results[SEL_LOCAL]; } else if ( obj instanceof DictInfo ) { ++results[SEL_REMOTE]; } else { + DbgUtils.logd( TAG, "obj is a: " + obj ); Assert.fail(); } } @@ -1200,8 +1216,10 @@ public class DictsDelegate extends ListDelegateBase XWListItem dictView = (XWListItem)toggled; String lang = dictView.getText(); if ( selected ) { - m_selDicts.put( lang, dictView ); + m_selViews.put( lang, dictView ); + m_selDicts.put( lang, dictView.getCached() ); } else { + m_selViews.remove( lang ); m_selDicts.remove( lang ); } invalidateOptionsMenuIf(); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java index 39c21a016..5062fb8e0 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java @@ -1040,6 +1040,7 @@ public class GamesListDelegate extends ListDelegateBase } } + @Override protected void onSaveInstanceState( Bundle outState ) { // super.onSaveInstanceState( outState ); @@ -1321,7 +1322,7 @@ public class GamesListDelegate extends ListDelegateBase doOpenGame( params ); break; case ENABLE_DUALPANE: - makeOkOnlyBuilder( R.string.dualpane_exit_now) + makeOkOnlyBuilder( R.string.dualpane_exit_now ) .setAction( Action.ENABLE_DUALPANE_EXIT ) .show(); break;