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.
This commit is contained in:
Eric House 2017-02-01 20:36:59 -08:00
parent 3ae2b41ae2
commit b0cef99507
2 changed files with 106 additions and 87 deletions

View file

@ -60,6 +60,8 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.Serializable;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -76,6 +78,10 @@ public class DictsDelegate extends ListDelegateBase
DownloadFinishedListener, XWListItem.ExpandedListener { DownloadFinishedListener, XWListItem.ExpandedListener {
private static final String TAG = DictsDelegate.class.getSimpleName(); 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_SHOWREMOTE = "do_launch";
protected static final String DICT_LANG_EXTRA = "use_lang"; protected static final String DICT_LANG_EXTRA = "use_lang";
protected static final String DICT_NAME_EXTRA = "use_dict"; protected static final String DICT_NAME_EXTRA = "use_dict";
@ -96,7 +102,8 @@ public class DictsDelegate extends ListDelegateBase
private CheckBox m_checkbox; private CheckBox m_checkbox;
private String[] m_locNames; private String[] m_locNames;
private String m_finishOnName; private String m_finishOnName;
private Map<String, XWListItem> m_selDicts; private Map<String, XWListItem> m_selViews;
private Map<String, Object> m_selDicts = new HashMap<String, Object>();
private String m_origTitle; private String m_origTitle;
private boolean m_showRemote = false; private boolean m_showRemote = false;
private String m_filterLang; 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_name;
public String m_lang; public String m_lang;
public int m_nWords; public int m_nWords;
@ -249,11 +256,11 @@ public class DictsDelegate extends ListDelegateBase
} }
result = item; result = item;
String name = null;
if ( dataObj instanceof DictAndLoc ) { if ( dataObj instanceof DictAndLoc ) {
DictAndLoc dal = (DictAndLoc)dataObj; DictAndLoc dal = (DictAndLoc)dataObj;
String name = dal.name; name = dal.name;
item.setText( name );
DictLoc loc = dal.loc; DictLoc loc = dal.loc;
item.setComment( m_locNames[loc.ordinal()] ); item.setComment( m_locNames[loc.ordinal()] );
@ -262,28 +269,27 @@ public class DictsDelegate extends ListDelegateBase
item.setOnClickListener( DictsDelegate.this ); item.setOnClickListener( DictsDelegate.this );
item.setExpandedListener( null ); // item might be reused 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 ) { } else if ( dataObj instanceof DictInfo ) {
DictInfo info = (DictInfo)dataObj; DictInfo info = (DictInfo)dataObj;
String name = info.m_name; name = info.m_name;
item.setText( name );
item.setCached( info ); item.setCached( info );
item.setExpandedListener( DictsDelegate.this ); item.setExpandedListener( DictsDelegate.this );
item.setExpanded( m_expandedItems.contains( info ) ); item.setExpanded( m_expandedItems.contains( info ) );
item.setComment( m_onServerStr ); item.setComment( m_onServerStr );
if ( m_selDicts.containsKey( name ) ) {
m_selDicts.put( name, item );
item.setSelected( true );
}
} else { } else {
Assert.fail(); Assert.fail();
} }
item.setText( name );
boolean selected = m_selDicts.containsKey( name );
if ( selected ) {
m_selViews.put( name, item );
}
item.setSelected( selected );
} }
return result; return result;
} }
@ -362,10 +368,10 @@ public class DictsDelegate extends ListDelegateBase
DlgID dlgID = DlgID.values()[id]; DlgID dlgID = DlgID.values()[id];
switch( dlgID ) { switch( dlgID ) {
case MOVE_DICT: case MOVE_DICT:
final XWListItem[] selItems = getSelItems(); final String[] selNames = getSelNames();
final int[] moveTo = { -1 }; final int[] moveTo = { -1 };
message = getString( R.string.move_dict_fmt, message = getString( R.string.move_dict_fmt,
getJoinedNames( selItems ) ); getJoinedSelNames(selNames) );
OnClickListener newSelLstnr = OnClickListener newSelLstnr =
new OnClickListener() { new OnClickListener() {
@ -389,7 +395,7 @@ public class DictsDelegate extends ListDelegateBase
DictsDelegate self = curThis(); DictsDelegate self = curThis();
DictLoc toLoc = self.itemToRealLoc( moveTo[0] ); DictLoc toLoc = self.itemToRealLoc( moveTo[0] );
Assert.assertTrue( self == DictsDelegate.this ); Assert.assertTrue( self == DictsDelegate.this );
moveDicts( selItems, toLoc ); moveDicts( selNames, toLoc );
} }
}; };
@ -403,23 +409,22 @@ public class DictsDelegate extends ListDelegateBase
break; break;
case SET_DEFAULT: case SET_DEFAULT:
final XWListItem row = m_selDicts.values().iterator().next(); final String name = m_selDicts.keySet().iterator().next();
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
DictsDelegate self = curThis(); DictsDelegate self = curThis();
if ( DialogInterface.BUTTON_NEGATIVE == item if ( DialogInterface.BUTTON_NEGATIVE == item
|| DialogInterface.BUTTON_POSITIVE == 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 ); R.string.key_default_robodict );
} }
if ( DialogInterface.BUTTON_NEGATIVE == item if ( DialogInterface.BUTTON_NEGATIVE == item
|| DialogInterface.BUTTON_NEUTRAL == 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 ); R.string.key_default_dict );
} }
} }
}; };
String name = row.getText();
String lang = DictLangCache.getLangName( m_activity, name); String lang = DictLangCache.getLangName( m_activity, name);
lang = xlateLang( lang ); lang = xlateLang( lang );
message = getString( R.string.set_default_message_fmt, name, 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 ) protected void init( Bundle savedInstanceState )
{ {
m_onServerStr = getString( R.string.dict_on_server ); 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 = (CheckBox)findViewById( R.id.show_remote );
m_checkbox.setOnClickListener( this ); m_checkbox.setOnClickListener( this );
mkListAdapter(); getBundledData( savedInstanceState );
m_checkbox.setSelected( m_showRemote );
Bundle args = getArguments(); Bundle args = getArguments();
if ( null != args ) { if ( null != args ) {
@ -556,6 +563,23 @@ public class DictsDelegate extends ListDelegateBase
super.onStop(); 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 ) public void onClick( View view )
{ {
if ( view == m_checkbox ) { if ( view == m_checkbox ) {
@ -631,13 +655,12 @@ public class DictsDelegate extends ListDelegateBase
Uri[] uris = new Uri[countNeedDownload()]; Uri[] uris = new Uri[countNeedDownload()];
String[] names = new String[uris.length]; String[] names = new String[uris.length];
int count = 0; int count = 0;
for ( Iterator<XWListItem> iter = m_selDicts.values().iterator();
iter.hasNext(); ) { for ( Map.Entry<String, Object> entry : m_selDicts.entrySet() ) {
XWListItem litm = iter.next(); Object cached = entry.getValue();
Object cached = litm.getCached();
if ( cached instanceof DictInfo ) { if ( cached instanceof DictInfo ) {
DictInfo info = (DictInfo)cached; DictInfo info = (DictInfo)cached;
String name = litm.getText(); String name = entry.getKey();
Uri uri = Utils.makeDictUri( m_activity, info.m_lang, Uri uri = Utils.makeDictUri( m_activity, info.m_lang,
name ); name );
uris[count] = uri; uris[count] = uri;
@ -654,36 +677,38 @@ public class DictsDelegate extends ListDelegateBase
return handled; return handled;
} }
private void moveDicts( XWListItem[] selItems, DictLoc toLoc ) private void moveDicts( String[] selNames, DictLoc toLoc )
{ {
if ( DictUtils.needsStoragePermission( toLoc ) ) { if ( DictUtils.needsStoragePermission( toLoc ) ) {
tryGetPerms( Perm.STORAGE, R.string.move_dict_rationale, tryGetPerms( Perm.STORAGE, R.string.move_dict_rationale,
Action.MOVE_CONFIRMED, selItems, toLoc ); Action.MOVE_CONFIRMED, selNames, toLoc );
} else { } else {
moveDictsWithPermission( selItems, toLoc ); moveDictsWithPermission( selNames, toLoc );
} }
} }
private void moveDictsWithPermission( Object[] params ) private void moveDictsWithPermission( Object[] params )
{ {
XWListItem[] selItems = (XWListItem[])params[0]; String[] selNames = (String[])params[0];
DictLoc toLoc = (DictLoc)params[1]; 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 ) { for ( String name : selNames ) {
DictLoc fromLoc = (DictLoc)selItem.getCached(); DictLoc fromLoc = (DictLoc)m_selDicts.get( name );
String name = selItem.getText();
if ( fromLoc == toLoc ) { if ( fromLoc == toLoc ) {
DbgUtils.logw( TAG, "not moving %s: same loc", name ); DbgUtils.logw( TAG, "not moving %s: same loc", name );
} else if ( DictUtils.moveDict( m_activity, } else if ( DictUtils.moveDict( m_activity,
name, fromLoc, name, fromLoc,
toLoc ) ) { toLoc ) ) {
if ( m_selViews.containsKey( name ) ) {
XWListItem selItem = m_selViews.get( name );
selItem.setComment( m_locNames[toLoc.ordinal()] ); selItem.setComment( m_locNames[toLoc.ordinal()] );
selItem.setCached( toLoc ); selItem.setCached( toLoc );
selItem.invalidate(); selItem.invalidate();
}
DBUtils.dictsMoveInfo( m_activity, name, DBUtils.dictsMoveInfo( m_activity, name,
fromLoc, toLoc ); fromLoc, toLoc );
} else { } else {
@ -691,7 +716,6 @@ public class DictsDelegate extends ListDelegateBase
DbgUtils.logw( TAG, "moveDict(%s) failed", name ); DbgUtils.logw( TAG, "moveDict(%s) failed", name );
} }
} }
} }
private void switchShowingRemote( boolean showRemote ) private void switchShowingRemote( boolean showRemote )
@ -712,10 +736,9 @@ public class DictsDelegate extends ListDelegateBase
private int countNeedDownload() private int countNeedDownload()
{ {
int result = 0; int result = 0;
for ( Iterator<XWListItem> iter = m_selDicts.values().iterator(); for ( Iterator<Object> iter = m_selDicts.values().iterator();
iter.hasNext(); ) { iter.hasNext(); ) {
XWListItem litm = iter.next(); Object obj = iter.next();
Object obj = litm.getCached();
if ( obj instanceof DictInfo ) { if ( obj instanceof DictInfo ) {
++result; ++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 ); int langCode = DictLangCache.getDictLangCode( m_activity, name );
String curLangName = XWPrefs.getPrefsString( m_activity, R.string.key_default_language ); String curLangName = XWPrefs.getPrefsString( m_activity, R.string.key_default_language );
int curLangCode = DictLangCache.getLangLangCode( m_activity, curLangName ); int curLangCode = DictLangCache.getLangLangCode( m_activity, curLangName );
@ -797,9 +819,9 @@ public class DictsDelegate extends ListDelegateBase
private boolean selItemsVolatile() private boolean selItemsVolatile()
{ {
boolean result = 0 < m_selDicts.size(); boolean result = 0 < m_selDicts.size();
for ( Iterator<XWListItem> iter = m_selDicts.values().iterator(); for ( Iterator<Object> iter = m_selDicts.values().iterator();
result && iter.hasNext(); ) { result && iter.hasNext(); ) {
Object obj = iter.next().getCached(); Object obj = iter.next();
if ( obj instanceof DictLoc ) { if ( obj instanceof DictLoc ) {
DictLoc loc = (DictLoc)obj; DictLoc loc = (DictLoc)obj;
if ( loc == DictLoc.BUILT_IN ) { if ( loc == DictLoc.BUILT_IN ) {
@ -814,9 +836,9 @@ public class DictsDelegate extends ListDelegateBase
private void deleteSelected() private void deleteSelected()
{ {
XWListItem[] items = getSelItems(); String[] names = getSelNames();
String msg = getQuantityString( R.plurals.confirm_delete_dict_fmt, 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 // Confirm. And for each dict, warn if (after ALL are deleted) any
// game will no longer be openable without downloading. For now // game will no longer be openable without downloading. For now
@ -845,8 +867,7 @@ public class DictsDelegate extends ListDelegateBase
Map<Integer, LangDelData> dels = new HashMap<Integer, LangDelData>(); Map<Integer, LangDelData> dels = new HashMap<Integer, LangDelData>();
Set<Integer> skipLangs = new HashSet<Integer>(); Set<Integer> skipLangs = new HashSet<Integer>();
for ( XWListItem item : items ) { for ( String dict : m_selDicts.keySet() ) {
String dict = item.getText();
int langCode = DictLangCache.getDictLangCode( m_activity, dict ); int langCode = DictLangCache.getDictLangCode( m_activity, dict );
if ( skipLangs.contains( langCode ) ) { if ( skipLangs.contains( langCode ) ) {
continue; continue;
@ -879,7 +900,7 @@ public class DictsDelegate extends ListDelegateBase
makeConfirmThenBuilder( msg, Action.DELETE_DICT_ACTION ) makeConfirmThenBuilder( msg, Action.DELETE_DICT_ACTION )
.setPosButton( R.string.button_delete ) .setPosButton( R.string.button_delete )
.setParams( (Object)items ) .setParams( (Object)names )
.show(); .show();
} // deleteSelected } // deleteSelected
@ -906,18 +927,18 @@ public class DictsDelegate extends ListDelegateBase
{ {
switch( action ) { switch( action ) {
case DELETE_DICT_ACTION: case DELETE_DICT_ACTION:
XWListItem[] items = (XWListItem[])params[0]; String[] names = (String[])params[0];
for ( XWListItem item : items ) { for ( String name : names ) {
String name = item.getText(); DictLoc loc = (DictLoc)m_selDicts.get( name );
DictLoc loc = (DictLoc)item.getCached();
deleteDict( name, loc ); deleteDict( name, loc );
} }
clearSelections(); clearSelections();
mkListAdapter(); mkListAdapter();
break; break;
case UPDATE_DICTS_ACTION: case UPDATE_DICTS_ACTION:
Uri[] uris = new Uri[m_needUpdates.size()]; Uri[] uris = new Uri[m_needUpdates.size()];
String[] names = new String[uris.length]; names = new String[uris.length];
int count = 0; int count = 0;
for ( Iterator<String> iter = m_needUpdates.keySet().iterator(); for ( Iterator<String> iter = m_needUpdates.keySet().iterator();
iter.hasNext(); ) { iter.hasNext(); ) {
@ -969,7 +990,7 @@ public class DictsDelegate extends ListDelegateBase
m_adapter = new DictListAdapter( m_activity ); m_adapter = new DictListAdapter( m_activity );
setListAdapterKeepScroll( m_adapter ); setListAdapterKeepScroll( m_adapter );
m_selDicts = new HashMap<String, XWListItem>(); m_selViews = new HashMap<String, XWListItem>();
} }
private void saveClosed() private void saveClosed()
@ -981,50 +1002,45 @@ public class DictsDelegate extends ListDelegateBase
private void clearSelections() private void clearSelections()
{ {
if ( 0 < m_selDicts.size() ) { if ( 0 < m_selDicts.size() ) {
XWListItem[] items = getSelItems(); for ( String name : getSelNames() ) {
if ( m_selViews.containsKey( name ) ) {
m_selDicts.clear(); XWListItem item = m_selViews.get( name );
for ( XWListItem item : items ) {
item.setSelected( false ); item.setSelected( false );
} }
} }
m_selDicts.clear();
m_selViews.clear();
}
} }
private String getJoinedNames( XWListItem[] items ) private String[] getSelNames()
{ {
String[] names = new String[items.length]; Set<String> nameSet = m_selDicts.keySet();
int ii = 0; String[] names = nameSet.toArray( new String[nameSet.size()] );
for ( XWListItem item : items ) { return names;
names[ii++] = item.getText();
} }
private String getJoinedSelNames(String[] names)
{
return TextUtils.join( ", ", names ); return TextUtils.join( ", ", names );
} }
private XWListItem[] getSelItems() private String getJoinedSelNames()
{ {
XWListItem[] items = new XWListItem[m_selDicts.size()]; String[] names = getSelNames();
int indx = 0; return getJoinedSelNames( names );
for ( Iterator<XWListItem> iter = m_selDicts.values().iterator();
iter.hasNext(); ) {
items[indx++] = iter.next();
} }
return items;
}
private int[] countSelDicts() private int[] countSelDicts()
{ {
int[] results = new int[2]; int[] results = new int[] { 0, 0 };
Assert.assertTrue( 0 == results[0] && 0 == results[1] ); for ( Object obj : m_selDicts.values() ) {
for ( Iterator<XWListItem> iter = m_selDicts.values().iterator();
iter.hasNext(); ) {
Object obj = iter.next().getCached();
if ( obj instanceof DictLoc ) { if ( obj instanceof DictLoc ) {
++results[SEL_LOCAL]; ++results[SEL_LOCAL];
} else if ( obj instanceof DictInfo ) { } else if ( obj instanceof DictInfo ) {
++results[SEL_REMOTE]; ++results[SEL_REMOTE];
} else { } else {
DbgUtils.logd( TAG, "obj is a: " + obj );
Assert.fail(); Assert.fail();
} }
} }
@ -1200,8 +1216,10 @@ public class DictsDelegate extends ListDelegateBase
XWListItem dictView = (XWListItem)toggled; XWListItem dictView = (XWListItem)toggled;
String lang = dictView.getText(); String lang = dictView.getText();
if ( selected ) { if ( selected ) {
m_selDicts.put( lang, dictView ); m_selViews.put( lang, dictView );
m_selDicts.put( lang, dictView.getCached() );
} else { } else {
m_selViews.remove( lang );
m_selDicts.remove( lang ); m_selDicts.remove( lang );
} }
invalidateOptionsMenuIf(); invalidateOptionsMenuIf();

View file

@ -1040,6 +1040,7 @@ public class GamesListDelegate extends ListDelegateBase
} }
} }
@Override
protected void onSaveInstanceState( Bundle outState ) protected void onSaveInstanceState( Bundle outState )
{ {
// super.onSaveInstanceState( outState ); // super.onSaveInstanceState( outState );
@ -1321,7 +1322,7 @@ public class GamesListDelegate extends ListDelegateBase
doOpenGame( params ); doOpenGame( params );
break; break;
case ENABLE_DUALPANE: case ENABLE_DUALPANE:
makeOkOnlyBuilder( R.string.dualpane_exit_now) makeOkOnlyBuilder( R.string.dualpane_exit_now )
.setAction( Action.ENABLE_DUALPANE_EXIT ) .setAction( Action.ENABLE_DUALPANE_EXIT )
.show(); .show();
break; break;