Merge branch 'android_branch' into android_thumbnail

Conflicts:
	xwords4/android/XWords4/res/values/strings.xml
This commit is contained in:
Eric House 2013-10-30 21:46:45 -07:00
commit 8ddc9a7770
12 changed files with 371 additions and 233 deletions

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="120"
height="120" xml:space="preserve">
<g
id="g12"
transform="matrix(1.25,0,0,-1.25,0,120)">
<g transform='translate(47.72,32.35)' id='g676'>
<path style='fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none' d='M 0,0 -16.37,22.32 -6.158,22.32 -6.158,43.16 6.056,43.16 6.056,22.32 16.37,22.32 0,0 z M -33.34,-5.839 -33.34,-11.85 33.9,-11.85 33.89,-5.839 -33.34,-5.839 z' id='path678'/>
</g></g>
</svg>

After

Width:  |  Height:  |  Size: 664 B

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/dicts_item_move"
android:title="@string/dicts_item_move"
/>
<item android:id="@+id/dicts_item_select"
android:title="@string/dicts_item_select"
/>
</menu>

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/dicts_download"
android:title="@string/download_dicts"
android:icon="@drawable/download__gen"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/dicts_delete"
android:title="@string/list_item_delete"
android:icon="@drawable/content_discard__gen"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/dicts_move"
android:title="@string/dicts_item_move"
/>
<item android:id="@+id/dicts_select"
android:title="@string/dicts_item_select"
/>
</menu>

View file

@ -231,9 +231,9 @@
wordlist delete confiration dialog in the case where the wordlist delete confiration dialog in the case where the
wordlist to be deleted is the last in its language. The name wordlist to be deleted is the last in its language. The name
of the language is substituted for %s. --> of the language is substituted for %s. -->
<string name="confirm_deleteonly_dictf">\u0020É a única lista de <!-- <string name="confirm_deleteonly_dictf">\u0020É a única lista de -->
palavras em %s instalada. Um ou mais jogos não poderão ser abertos <!-- palavras em %s instalada. Um ou mais jogos não poderão ser abertos -->
sem ela.</string> <!-- sem ela.</string> -->
<!-- Additional text appended to text confirm_delete_dictf in the <!-- Additional text appended to text confirm_delete_dictf in the
wordlist delete confiration dialog in the case where the wordlist delete confiration dialog in the case where the
wordlist to be deleted is NOT the last in its language. The wordlist to be deleted is NOT the last in its language. The
@ -252,9 +252,9 @@
<!-- Used as the text fo the confirming/querying dialog that goes <!-- Used as the text fo the confirming/querying dialog that goes
up when the dicts_item_select menuitem is chosen. The up when the dicts_item_select menuitem is chosen. The
possible answers are the three button text strings below. --> possible answers are the three button text strings below. -->
<string name="set_default_messagef">Para que jogadores essa lista <!-- <string name="set_default_messagef">Para que jogadores essa lista -->
de palavras deve ser a padrão para novos jogos? (o idioma %s será <!-- de palavras deve ser a padrão para novos jogos? (o idioma %s será -->
padrão para ambos.)</string> <!-- padrão para ambos.)</string> -->
<!-- These three strings are the text for three buttons giving <!-- These three strings are the text for three buttons giving
choices in respose to the dialog launched in response to the choices in respose to the dialog launched in response to the

View file

@ -225,13 +225,13 @@
wordlist is substituted for %s. Sometimes one of the two wordlist is substituted for %s. Sometimes one of the two
strings below is appended. --> strings below is appended. -->
<string name="confirm_delete_dictf">Are you sure you want to <string name="confirm_delete_dictf">Are you sure you want to
delete %s?</string> delete the wordlist[s] %s?</string>
<!-- Additional text appended to text confirm_delete_dictf in the <!-- Additional text appended to text confirm_delete_dictf in the
wordlist delete confiration dialog in the case where the wordlist delete confiration dialog in the case where the
wordlist to be deleted is the last in its language. The name wordlist to be deleted is the last in its language. The name
of the language is substituted for %s. --> of the language is substituted for %s. -->
<string name="confirm_deleteonly_dictf">\u0020It is the only %s <string name="confirm_deleteonly_dictf">%1$s is the only %2$s
wordlist installed. One or more games will be unopenable wordlist installed. One or more games will be unopenable
without it.</string> without it.</string>
<!-- Additional text appended to text confirm_delete_dictf in the <!-- Additional text appended to text confirm_delete_dictf in the
@ -252,8 +252,8 @@
<!-- Used as the text fo the confirming/querying dialog that goes <!-- Used as the text fo the confirming/querying dialog that goes
up when the dicts_item_select menuitem is chosen. The up when the dicts_item_select menuitem is chosen. The
possible answers are the three button text strings below. --> possible answers are the three button text strings below. -->
<string name="set_default_messagef">For what players should this <string name="set_default_messagef">For what players should the
wordlist be the default for new games? (The language %s will be wordlist %1$s be the default for new games? (The language %2$s will be
the default for both.)</string> the default for both.)</string>
<!-- These three strings are the text for three buttons giving <!-- These three strings are the text for three buttons giving
@ -2156,6 +2156,6 @@
<string name="sel_gamesf">Games: %d"</string> <string name="sel_gamesf">Games: %d"</string>
<string name="sel_groupsf">Groups: %d"</string> <string name="sel_groupsf">Groups: %d"</string>
<string name="summary_thumbsize">Thumbnail size</string> <string name="summary_thumbsize">Thumbnail size</string>
<string name="sel_dictsf">Wordlists: %d"</string>
</resources> </resources>

View file

@ -20,6 +20,7 @@
package org.eehouse.android.xw4; package org.eehouse.android.xw4;
import android.text.TextUtils;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
@ -33,8 +34,6 @@ import android.database.DataSetObserver;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextMenu;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@ -43,24 +42,28 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.ExpandableListAdapter; import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ExpandableListView; import android.widget.ExpandableListView;
import android.widget.AdapterView;
import android.widget.PopupMenu; import android.widget.PopupMenu;
import android.widget.TextView; import android.widget.TextView;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import junit.framework.Assert; import junit.framework.Assert;
import org.eehouse.android.xw4.DictUtils.DictAndLoc; import org.eehouse.android.xw4.DictUtils.DictAndLoc;
import org.eehouse.android.xw4.jni.XwJNI; import org.eehouse.android.xw4.jni.XwJNI;
import org.eehouse.android.xw4.jni.JNIUtilsImpl; import org.eehouse.android.xw4.jni.JNIUtilsImpl;
import org.eehouse.android.xw4.jni.GameSummary;
import org.eehouse.android.xw4.DictUtils.DictLoc; import org.eehouse.android.xw4.DictUtils.DictLoc;
public class DictsActivity extends XWExpandableListActivity public class DictsActivity extends XWExpandableListActivity
implements View.OnClickListener, XWListItem.DeleteCallback, implements View.OnClickListener, AdapterView.OnItemLongClickListener,
MountEventReceiver.SDCardNotifiee, DlgDelegate.DlgClickNotify, SelectableItem, MountEventReceiver.SDCardNotifiee,
DlgDelegate.DlgClickNotify,
DictImportActivity.DownloadFinishedListener { DictImportActivity.DownloadFinishedListener {
private static interface SafePopup { private static interface SafePopup {
@ -71,11 +74,6 @@ public class DictsActivity extends XWExpandableListActivity
private static final String DICT_DOLAUNCH = "do_launch"; private static final String DICT_DOLAUNCH = "do_launch";
private static final String DICT_LANG_EXTRA = "use_lang"; private static final String DICT_LANG_EXTRA = "use_lang";
private static final String DICT_NAME_EXTRA = "use_dict"; 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 HashSet<String> m_closedLangs; private HashSet<String> m_closedLangs;
@ -90,19 +88,14 @@ public class DictsActivity extends XWExpandableListActivity
// settle for a hash on the side. // settle for a hash on the side.
private static HashMap<MenuItem, DictAndLoc> s_itemData; private static HashMap<MenuItem, DictAndLoc> s_itemData;
private int m_lang = 0;
private String[] m_langs; private String[] m_langs;
private String m_name = null;
private String m_deleteDict = null;
private String m_download; private String m_download;
private ExpandableListView m_expView; private ExpandableListView m_expView;
private String[] m_locNames; private String[] m_locNames;
private DictListAdapter m_adapter; private DictListAdapter m_adapter;
private HashSet<XWListItem> m_selDicts;
private CharSequence m_origTitle;
private long m_packedPosition;
private DictLoc m_moveFromLoc;
private int m_moveFromItem;
private int m_moveToItm;
private boolean m_launchedForMissing = false; private boolean m_launchedForMissing = false;
private LayoutInflater m_factory; private LayoutInflater m_factory;
@ -144,6 +137,7 @@ public class DictsActivity extends XWExpandableListActivity
if ( null == view ) { if ( null == view ) {
view = (XWListItem) view = (XWListItem)
m_factory.inflate( R.layout.list_item, null ); m_factory.inflate( R.layout.list_item, null );
view.setSelCB( DictsActivity.this );
int lang = (int)getGroupId( groupPosition ); int lang = (int)getGroupId( groupPosition );
DictAndLoc[] dals = DictLangCache.getDALsHaveLang( m_context, DictAndLoc[] dals = DictLangCache.getDALsHaveLang( m_context,
@ -157,9 +151,6 @@ public class DictsActivity extends XWExpandableListActivity
DictLoc loc = dal.loc; DictLoc loc = dal.loc;
view.setComment( m_locNames[loc.ordinal()] ); view.setComment( m_locNames[loc.ordinal()] );
view.cache( loc ); view.cache( loc );
if ( DictLoc.BUILT_IN != loc ) {
view.setDeleteCallback( DictsActivity.this );
}
} else { } else {
view.setText( m_download ); view.setText( m_download );
} }
@ -237,11 +228,8 @@ public class DictsActivity extends XWExpandableListActivity
protected XWListItem getSelChildView() protected XWListItem getSelChildView()
{ {
int groupPosition = Assert.assertTrue( 1 == m_selDicts.size() );
ExpandableListView.getPackedPositionGroup( m_packedPosition ); return m_selDicts.iterator().next();
int childPosition =
ExpandableListView.getPackedPositionChild( m_packedPosition );
return (XWListItem)getChildView( groupPosition, childPosition );
} }
private void addToCache( int group, int child, XWListItem view ) private void addToCache( int group, int child, XWListItem view )
@ -268,45 +256,48 @@ public class DictsActivity extends XWExpandableListActivity
switch( id ) { switch( id ) {
case MOVE_DICT: case MOVE_DICT:
final XWListItem[] selItems = getSelItems();
final int[] moveTo = { -1 };
message = Utils.format( this, R.string.move_dictf, message = Utils.format( this, R.string.move_dictf,
m_adapter.getSelChildView().getText() ); getJoinedNames( selItems ) );
OnClickListener newSelLstnr = OnClickListener newSelLstnr =
new OnClickListener() { new OnClickListener() {
public void onClick( DialogInterface dlgi, int item ) { public void onClick( DialogInterface dlgi, int item ) {
m_moveToItm = item; moveTo[0] = item;
AlertDialog dlg = (AlertDialog)dlgi; AlertDialog dlg = (AlertDialog)dlgi;
Button btn = Button btn =
dlg.getButton( AlertDialog.BUTTON_POSITIVE ); dlg.getButton( AlertDialog.BUTTON_POSITIVE );
btn.setEnabled( m_moveToItm != m_moveFromItem ); btn.setEnabled( true );
} }
}; };
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
XWListItem rowView = m_adapter.getSelChildView(); DictLoc toLoc = itemToRealLoc( moveTo[0] );
Assert.assertTrue( m_moveToItm != m_moveFromItem ); for ( XWListItem selItem : selItems ) {
DictLoc toLoc = itemToRealLoc( m_moveToItm ); DictLoc fromLoc = (DictLoc)selItem.getCached();
if ( DictUtils.moveDict( DictsActivity.this, String name = selItem.getText();
rowView.getText(), if ( fromLoc == toLoc ) {
m_moveFromLoc, DbgUtils.logf( "not moving %s: same loc", name );
} else if ( DictUtils.moveDict( DictsActivity.this,
name, fromLoc,
toLoc ) ) { toLoc ) ) {
rowView.setComment( m_locNames[toLoc.ordinal()] ); selItem.setComment( m_locNames[toLoc.ordinal()] );
rowView.cache( toLoc ); selItem.cache( toLoc );
rowView.invalidate(); selItem.invalidate();
DBUtils.dictsMoveInfo( DictsActivity.this, DBUtils.dictsMoveInfo( DictsActivity.this,
rowView.getText(), name, fromLoc, toLoc );
m_moveFromLoc, toLoc );
} else { } else {
DbgUtils.logf( "moveDict(%s) failed", DbgUtils.logf( "moveDict(%s) failed", name );
rowView.getText() ); }
} }
} }
}; };
dialog = new AlertDialog.Builder( this ) dialog = new AlertDialog.Builder( this )
.setTitle( message ) .setTitle( message )
.setSingleChoiceItems( makeDictDirItems(), m_moveFromItem, .setSingleChoiceItems( makeDictDirItems(), moveTo[0],
newSelLstnr ) newSelLstnr )
.setPositiveButton( R.string.button_move, lstnr ) .setPositiveButton( R.string.button_move, lstnr )
.setNegativeButton( R.string.button_cancel, null ) .setNegativeButton( R.string.button_cancel, null )
@ -314,22 +305,22 @@ public class DictsActivity extends XWExpandableListActivity
break; break;
case SET_DEFAULT: case SET_DEFAULT:
final XWListItem row = m_selDicts.iterator().next();
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
if ( DialogInterface.BUTTON_NEGATIVE == item if ( DialogInterface.BUTTON_NEGATIVE == item
|| DialogInterface.BUTTON_POSITIVE == item ) { || DialogInterface.BUTTON_POSITIVE == item ) {
setDefault( R.string.key_default_dict ); setDefault( row, R.string.key_default_dict );
} }
if ( DialogInterface.BUTTON_NEGATIVE == item if ( DialogInterface.BUTTON_NEGATIVE == item
|| DialogInterface.BUTTON_NEUTRAL == item ) { || DialogInterface.BUTTON_NEUTRAL == item ) {
setDefault( R.string.key_default_robodict ); setDefault( row, R.string.key_default_robodict );
} }
} }
}; };
XWListItem rowView = m_adapter.getSelChildView(); String name = row.getText();
String lang = String lang = DictLangCache.getLangName( this, name);
DictLangCache.getLangName( this, rowView.getText() ); message = getString( R.string.set_default_messagef, name, lang );
message = getString( R.string.set_default_messagef, lang );
dialog = new AlertDialog.Builder( this ) dialog = new AlertDialog.Builder( this )
.setTitle( R.string.query_title ) .setTitle( R.string.query_title )
.setMessage( message ) .setMessage( message )
@ -392,7 +383,6 @@ public class DictsActivity extends XWExpandableListActivity
protected void onCreate( Bundle savedInstanceState ) protected void onCreate( Bundle savedInstanceState )
{ {
super.onCreate( savedInstanceState ); super.onCreate( savedInstanceState );
getBundledData( savedInstanceState );
m_closedLangs = new HashSet<String>(); m_closedLangs = new HashSet<String>();
String[] closed = XWPrefs.getClosedLangs( this ); String[] closed = XWPrefs.getClosedLangs( this );
@ -411,15 +401,13 @@ public class DictsActivity extends XWExpandableListActivity
setContentView( R.layout.dict_browse ); setContentView( R.layout.dict_browse );
m_expView = getExpandableListView(); m_expView = getExpandableListView();
registerForContextMenu( m_expView ); m_expView.setOnItemLongClickListener( this );
Button download = (Button)findViewById( R.id.download ); Button download = (Button)findViewById( R.id.download );
download.setOnClickListener( this ); download.setOnClickListener( this );
mkListAdapter(); mkListAdapter();
m_selDicts = new HashSet<XWListItem>();
// showNotAgainDlg( R.string.not_again_dicts,
// R.string.key_notagain_dicts );
Intent intent = getIntent(); Intent intent = getIntent();
if ( null != intent ) { if ( null != intent ) {
@ -436,6 +424,8 @@ public class DictsActivity extends XWExpandableListActivity
downloadNewDict( intent ); downloadNewDict( intent );
} }
} }
m_origTitle = getTitle();
} // onCreate } // onCreate
@Override @Override
@ -448,35 +438,6 @@ public class DictsActivity extends XWExpandableListActivity
expandGroups(); expandGroups();
} }
@Override
protected void onSaveInstanceState( Bundle outState )
{
super.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() );
}
}
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 = DictLoc.values()[tmp];
}
}
}
@Override @Override
protected void onStop() { protected void onStop() {
MountEventReceiver.unregister( this ); MountEventReceiver.unregister( this );
@ -495,65 +456,60 @@ public class DictsActivity extends XWExpandableListActivity
} }
@Override @Override
public void onCreateContextMenu( ContextMenu menu, View view, public void onBackPressed() {
ContextMenuInfo menuInfo ) if ( 0 == m_selDicts.size() ) {
{ super.onBackPressed();
super.onCreateContextMenu( menu, view, menuInfo ); } else {
clearSelections();
ExpandableListView.ExpandableListContextMenuInfo info
= (ExpandableListView.ExpandableListContextMenuInfo)menuInfo;
long packedPosition = info.packedPosition;
int childPosition = ExpandableListView.
getPackedPositionChild( packedPosition );
// int groupPosition = ExpandableListView.
// getPackedPositionGroup( packedPosition );
// DbgUtils.logf( "onCreateContextMenu: group: %d; child: %d",
// groupPosition, childPosition );
// We don't have a menu yet for languages, just for their dict
// children
if ( childPosition >= 0 ) {
MenuInflater inflater = getMenuInflater();
inflater.inflate( R.menu.dicts_item_menu, menu );
XWListItem row = (XWListItem)info.targetView;
DictLoc loc = (DictLoc)row.getCached();
if ( loc == DictLoc.BUILT_IN
|| ! DictUtils.haveWriteableSD() ) {
menu.removeItem( R.id.dicts_item_move );
}
String title = getString( R.string.game_item_menu_titlef,
row.getText() );
menu.setHeaderTitle( title );
} }
} }
@Override @Override
public boolean onContextItemSelected( MenuItem item ) public boolean onCreateOptionsMenu( Menu menu )
{ {
boolean handled = false; MenuInflater inflater = getMenuInflater();
ExpandableListContextMenuInfo info = null; inflater.inflate( R.menu.dicts_menu, menu );
try {
info = (ExpandableListContextMenuInfo)item.getMenuInfo(); return true;
} catch (ClassCastException cce) {
DbgUtils.loge( cce );
return false;
} }
m_packedPosition = info.packedPosition; @Override
public boolean onPrepareOptionsMenu( Menu menu )
{
int nSel = m_selDicts.size();
Utils.setItemVisible( menu, R.id.dicts_download, 0 == nSel );
Utils.setItemVisible( menu, R.id.dicts_select, 1 == nSel );
int id = item.getItemId(); boolean allVolatile = selItemsVolatile();
switch( id ) { Utils.setItemVisible( menu, R.id.dicts_move,
case R.id.dicts_item_move: allVolatile && DictUtils.haveWriteableSD() );
askMoveDict( (XWListItem)info.targetView ); Utils.setItemVisible( menu, R.id.dicts_delete, allVolatile );
return super.onPrepareOptionsMenu( menu );
}
public boolean onOptionsItemSelected( MenuItem item )
{
boolean handled = true;
switch ( item.getItemId() ) {
case R.id.dicts_download:
startDownload( 0, null );
break; break;
case R.id.dicts_item_select: case R.id.dicts_delete:
deleteSelected();
break;
case R.id.dicts_move:
askMoveSelDicts();
break;
case R.id.dicts_select:
showDialog( SET_DEFAULT ); showDialog( SET_DEFAULT );
break; break;
default:
handled = false;
} }
return handled; return handled || super.onOptionsItemSelected( item );
} }
private void downloadNewDict( Intent intent ) private void downloadNewDict( Intent intent )
@ -567,9 +523,8 @@ public class DictsActivity extends XWExpandableListActivity
} }
} }
private void setDefault( int keyId ) private void setDefault( XWListItem view, int keyId )
{ {
XWListItem view = m_adapter.getSelChildView();
SharedPreferences sp SharedPreferences sp
= PreferenceManager.getDefaultSharedPreferences( this ); = PreferenceManager.getDefaultSharedPreferences( this );
SharedPreferences.Editor editor = sp.edit(); SharedPreferences.Editor editor = sp.edit();
@ -582,20 +537,39 @@ public class DictsActivity extends XWExpandableListActivity
// Move dict. Put up dialog asking user to confirm move from XX // Move dict. Put up dialog asking user to confirm move from XX
// to YY. So we need both XX and YY. There may be several // to YY. So we need both XX and YY. There may be several
// options for YY? // options for YY?
private void askMoveDict( XWListItem item ) private void askMoveSelDicts()
{ {
m_moveFromLoc = (DictLoc)item.getCached();
showDialog( MOVE_DICT ); showDialog( MOVE_DICT );
} }
// XWListItem.DeleteCallback interface // OnItemLongClickListener interface
public void deleteCalled( XWListItem item ) public boolean onItemLongClick( AdapterView<?> parent, View view,
{ int position, long id ) {
String dict = item.getText(); boolean success = view instanceof SelectableItem.LongClickHandler;
String msg = getString( R.string.confirm_delete_dictf, dict ); if ( success ) {
((SelectableItem.LongClickHandler)view).longClicked();
}
return success;
}
m_deleteDict = dict; private boolean selItemsVolatile()
m_moveFromLoc = (DictLoc)item.getCached(); {
boolean result = 0 < m_selDicts.size();
for ( Iterator<XWListItem> iter = m_selDicts.iterator();
result && iter.hasNext(); ) {
DictLoc loc = (DictLoc)iter.next().getCached();
if ( loc == DictLoc.BUILT_IN ) {
result = false;
}
}
return result;
}
private void deleteSelected()
{
XWListItem[] items = getSelItems();
String msg = getString( R.string.confirm_delete_dictf,
getJoinedNames( items ) );
// When and what to warn about. First off, if there's another // When and what to warn about. First off, if there's another
// identical dict, simply confirm. Or if nobody's using this // identical dict, simply confirm. Or if nobody's using this
@ -604,30 +578,36 @@ public class DictsActivity extends XWExpandableListActivity
// want different warnings depending on whether it's the last // want different warnings depending on whether it's the last
// available dict in its language. // available dict in its language.
for ( XWListItem item : items ) {
String dict = item.getText();
if ( 1 < DictLangCache.getDictCount( this, dict ) ) { if ( 1 < DictLangCache.getDictCount( this, dict ) ) {
// there's another; do nothing // there's another; do nothing
} else { } else {
int fmtid = 0; String newMsg = null;
int langcode = DictLangCache.getDictLangCode( this, dict ); int langcode = DictLangCache.getDictLangCode( this, dict );
String langName = DictLangCache.getLangName( this, langcode );
DictAndLoc[] langDals = DictLangCache.getDALsHaveLang( this, DictAndLoc[] langDals = DictLangCache.getDALsHaveLang( this,
langcode ); langcode );
int nUsingLang = DBUtils.countGamesUsingLang( this, langcode ); int nUsingLang = DBUtils.countGamesUsingLang( this, langcode );
if ( 1 == langDals.length ) { // last in this language? if ( 1 == langDals.length ) { // last in this language?
if ( 0 < nUsingLang ) { if ( 0 < nUsingLang ) {
fmtid = R.string.confirm_deleteonly_dictf; newMsg = getString( R.string.confirm_deleteonly_dictf,
dict, langName );
} }
} else if ( 0 < DBUtils.countGamesUsingDict( this, dict ) ) { } else if ( 0 < DBUtils.countGamesUsingDict( this, dict ) ) {
fmtid = R.string.confirm_deletemore_dictf; newMsg = getString( R.string.confirm_deletemore_dictf,
langName );
}
if ( null != newMsg ) {
msg += "\n\n" + newMsg;
} }
if ( 0 != fmtid ) {
msg += getString( fmtid, DictLangCache.
getLangName( this, langcode ) );
} }
} }
showConfirmThen( msg, R.string.button_delete, DELETE_DICT_ACTION ); showConfirmThen( msg, R.string.button_delete, DELETE_DICT_ACTION,
} (Object)items );
} // deleteSelected
// MountEventReceiver.SDCardNotifiee interface // MountEventReceiver.SDCardNotifiee interface
public void cardMounted( boolean nowMounted ) public void cardMounted( boolean nowMounted )
@ -649,7 +629,13 @@ public class DictsActivity extends XWExpandableListActivity
switch( id ) { switch( id ) {
case DELETE_DICT_ACTION: case DELETE_DICT_ACTION:
if ( DialogInterface.BUTTON_POSITIVE == which ) { if ( DialogInterface.BUTTON_POSITIVE == which ) {
deleteDict( m_deleteDict, m_moveFromLoc ); XWListItem[] items = (XWListItem[])params[0];
for ( XWListItem item : items ) {
String name = item.getText();
DictLoc loc = (DictLoc)item.getCached();
deleteDict( name, loc );
}
clearSelections();
} }
break; break;
default: default:
@ -711,6 +697,49 @@ public class DictsActivity extends XWExpandableListActivity
XWPrefs.setClosedLangs( this, asArray ); XWPrefs.setClosedLangs( this, asArray );
} }
private void clearSelections()
{
if ( 0 < m_selDicts.size() ) {
XWListItem[] items = getSelItems();
m_selDicts.clear();
for ( XWListItem item : items ) {
item.setSelected( false );
}
}
}
private String getJoinedNames( XWListItem[] items )
{
String[] names = new String[items.length];
int ii = 0;
for ( XWListItem item : items ) {
names[ii++] = item.getText();
}
return TextUtils.join( ", ", names );
}
private XWListItem[] getSelItems()
{
XWListItem[] items = new XWListItem[m_selDicts.size()];
int indx = 0;
for ( Iterator<XWListItem> iter = m_selDicts.iterator();
iter.hasNext(); ) {
items[indx++] = iter.next();
}
return items;
}
private void setTitleBar()
{
int nSels = m_selDicts.size();
if ( 0 < nSels ) {
setTitle( getString( R.string.sel_dictsf, nSels ) );
} else {
setTitle( m_origTitle );
}
}
private String[] makeDictDirItems() private String[] makeDictDirItems()
{ {
@ -723,9 +752,6 @@ public class DictsActivity extends XWExpandableListActivity
if ( !showDownload && DictLoc.DOWNLOAD == loc ) { if ( !showDownload && DictLoc.DOWNLOAD == loc ) {
continue; continue;
} }
if ( loc.equals( m_moveFromLoc ) ) {
m_moveFromItem = nextI;
}
items[nextI++] = m_locNames[loc.ordinal()]; items[nextI++] = m_locNames[loc.ordinal()];
} }
return items; return items;
@ -793,6 +819,32 @@ public class DictsActivity extends XWExpandableListActivity
} }
} }
// SelectableItem interface
public void itemClicked( SelectableItem.LongClickHandler clicked,
GameSummary summary )
{
DbgUtils.logf( "itemClicked not implemented" );
}
public void itemToggled( SelectableItem.LongClickHandler toggled,
boolean selected )
{
XWListItem dictView = (XWListItem)toggled;
if ( selected ) {
m_selDicts.add( dictView );
} else {
m_selDicts.remove( dictView );
}
Utils.invalidateOptionsMenuIf( this );
setTitleBar();
}
public boolean getSelected( SelectableItem.LongClickHandler obj )
{
XWListItem dictView = (XWListItem)obj;
return m_selDicts.contains( dictView );
}
private static class SafePopupImpl implements SafePopup { private static class SafePopupImpl implements SafePopup {
public void doPopup( final Context context, View button, public void doPopup( final Context context, View button,
String curDict ) { String curDict ) {

View file

@ -45,24 +45,12 @@ public class GameListAdapter implements ExpandableListAdapter {
private ExpandableListView m_list; private ExpandableListView m_list;
private int m_fieldID; private int m_fieldID;
private Handler m_handler; private Handler m_handler;
private LoadItemCB m_cb; private SelectableItem m_cb;
private long[] m_positions; private long[] m_positions;
public interface LoadItemCB {
public void itemClicked( GameListAdapter.ClickHandler clicked,
GameSummary summary );
public void itemToggled( GameListAdapter.ClickHandler toggled,
boolean selected );
public boolean getSelected( GameListAdapter.ClickHandler obj );
}
public interface ClickHandler {
public void longClicked();
}
public GameListAdapter( Context context, ExpandableListView list, public GameListAdapter( Context context, ExpandableListView list,
Handler handler, LoadItemCB cb, long[] positions, Handler handler, SelectableItem cb,
String fieldName ) long[] positions, String fieldName )
{ {
m_context = context; m_context = context;
m_list = list; m_list = list;

View file

@ -28,17 +28,17 @@ import android.view.View;
import org.eehouse.android.xw4.DBUtils.GameGroupInfo; import org.eehouse.android.xw4.DBUtils.GameGroupInfo;
public class GameListGroup extends ExpiringTextView public class GameListGroup extends ExpiringTextView
implements GameListAdapter.ClickHandler implements SelectableItem.LongClickHandler
{ {
private int m_groupPosition; private int m_groupPosition;
private long m_groupID; private long m_groupID;
private boolean m_expanded; private boolean m_expanded;
private GameListAdapter.LoadItemCB m_cb; private SelectableItem m_cb;
public static GameListGroup makeForPosition( Context context, public static GameListGroup makeForPosition( Context context,
int groupPosition, int groupPosition,
long groupID, long groupID,
GameListAdapter.LoadItemCB cb ) SelectableItem cb )
{ {
GameListGroup result = GameListGroup result =
(GameListGroup)Utils.inflate( context, R.layout.game_list_group ); (GameListGroup)Utils.inflate( context, R.layout.game_list_group );

View file

@ -44,7 +44,7 @@ import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
import org.eehouse.android.xw4.jni.GameSummary; import org.eehouse.android.xw4.jni.GameSummary;
public class GameListItem extends LinearLayout public class GameListItem extends LinearLayout
implements View.OnClickListener, GameListAdapter.ClickHandler { implements View.OnClickListener, SelectableItem.LongClickHandler {
private static HashSet<Long> s_invalRows = new HashSet<Long>(); private static HashSet<Long> s_invalRows = new HashSet<Long>();
@ -59,7 +59,7 @@ public class GameListItem extends LinearLayout
private ImageButton m_expandButton; private ImageButton m_expandButton;
private Handler m_handler; private Handler m_handler;
private GameSummary m_summary; private GameSummary m_summary;
private GameListAdapter.LoadItemCB m_cb; private SelectableItem m_cb;
private int m_fieldID; private int m_fieldID;
private int m_loadingCount; private int m_loadingCount;
private int m_groupPosition; private int m_groupPosition;
@ -89,7 +89,7 @@ public class GameListItem extends LinearLayout
} }
private void init( Handler handler, long rowid, int groupPosition, private void init( Handler handler, long rowid, int groupPosition,
int fieldID, GameListAdapter.LoadItemCB cb ) int fieldID, SelectableItem cb )
{ {
m_handler = handler; m_handler = handler;
m_rowid = rowid; m_rowid = rowid;
@ -358,7 +358,7 @@ public class GameListItem extends LinearLayout
public static GameListItem makeForRow( Context context, long rowid, public static GameListItem makeForRow( Context context, long rowid,
Handler handler, int groupPosition, Handler handler, int groupPosition,
int fieldID, int fieldID,
GameListAdapter.LoadItemCB cb ) SelectableItem cb )
{ {
GameListItem result = GameListItem result =
(GameListItem)Utils.inflate( context, R.layout.game_list_item ); (GameListItem)Utils.inflate( context, R.layout.game_list_item );

View file

@ -58,8 +58,7 @@ import org.eehouse.android.xw4.jni.*;
public class GamesList extends XWExpandableListActivity public class GamesList extends XWExpandableListActivity
implements OnItemLongClickListener, implements OnItemLongClickListener,
DBUtils.DBChangeListener, DBUtils.DBChangeListener, SelectableItem,
GameListAdapter.LoadItemCB,
DictImportActivity.DownloadFinishedListener { DictImportActivity.DownloadFinishedListener {
private static final int WARN_NODICT = DlgDelegate.DIALOG_LAST + 1; private static final int WARN_NODICT = DlgDelegate.DIALOG_LAST + 1;
@ -473,9 +472,9 @@ public class GamesList extends XWExpandableListActivity
// OnItemLongClickListener interface // OnItemLongClickListener interface
public boolean onItemLongClick( AdapterView<?> parent, View view, public boolean onItemLongClick( AdapterView<?> parent, View view,
int position, long id ) { int position, long id ) {
boolean success = view instanceof GameListAdapter.ClickHandler; boolean success = view instanceof SelectableItem.LongClickHandler;
if ( success ) { if ( success ) {
((GameListAdapter.ClickHandler)view).longClicked(); ((SelectableItem.LongClickHandler)view).longClicked();
} }
return success; return success;
} }
@ -494,8 +493,8 @@ public class GamesList extends XWExpandableListActivity
} ); } );
} }
// GameListAdapter.LoadItemCB interface // SelectableItem interface
public void itemClicked( GameListAdapter.ClickHandler clicked, public void itemClicked( SelectableItem.LongClickHandler clicked,
GameSummary summary ) GameSummary summary )
{ {
// We need a way to let the user get back to the basic-config // We need a way to let the user get back to the basic-config
@ -512,7 +511,7 @@ public class GamesList extends XWExpandableListActivity
} }
} }
public void itemToggled( GameListAdapter.ClickHandler toggled, public void itemToggled( SelectableItem.LongClickHandler toggled,
boolean selected ) boolean selected )
{ {
if ( toggled instanceof GameListItem ) { if ( toggled instanceof GameListItem ) {
@ -536,7 +535,7 @@ public class GamesList extends XWExpandableListActivity
setTitleBar(); setTitleBar();
} }
public boolean getSelected( GameListAdapter.ClickHandler obj ) public boolean getSelected( SelectableItem.LongClickHandler obj )
{ {
boolean selected; boolean selected;
if ( obj instanceof GameListItem ) { if ( obj instanceof GameListItem ) {

View file

@ -0,0 +1,38 @@
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
/*
* Copyright 2009-2013 by Eric House (xwords@eehouse.org). All
* rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.eehouse.android.xw4;
import org.eehouse.android.xw4.jni.GameSummary;
// Interfaces used for (list) items that are selectable via
// long-tapping.
public interface SelectableItem {
public interface LongClickHandler {
public void longClicked();
}
public void itemClicked( LongClickHandler clicked, GameSummary summary );
public void itemToggled( LongClickHandler toggled, boolean selected );
public boolean getSelected( LongClickHandler obj );
}

View file

@ -20,19 +20,25 @@
package org.eehouse.android.xw4; package org.eehouse.android.xw4;
import android.widget.LinearLayout;
import android.view.View;
import android.widget.TextView;
import android.widget.ImageButton;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
public class XWListItem extends LinearLayout {
public class XWListItem extends LinearLayout
implements SelectableItem.LongClickHandler {
private int m_position; private int m_position;
private Context m_context; private Context m_context;
private Object m_cached; private Object m_cached;
private DeleteCallback m_cb; private DeleteCallback m_delCb;
private Drawable m_origDrawable;
private boolean m_selected = false;
private SelectableItem m_selCb;
public interface DeleteCallback { public interface DeleteCallback {
void deleteCalled( XWListItem item ); void deleteCalled( XWListItem item );
@ -69,17 +75,29 @@ public class XWListItem extends LinearLayout {
public void setDeleteCallback( DeleteCallback cb ) public void setDeleteCallback( DeleteCallback cb )
{ {
m_cb = cb; m_delCb = cb;
ImageButton button = (ImageButton)findViewById( R.id.del ); ImageButton button = (ImageButton)findViewById( R.id.del );
button.setOnClickListener( new View.OnClickListener() { button.setOnClickListener( new View.OnClickListener() {
@Override @Override
public void onClick( View view ) { public void onClick( View view ) {
m_cb.deleteCalled( XWListItem.this ); m_delCb.deleteCalled( XWListItem.this );
} }
} ); } );
button.setVisibility( View.VISIBLE ); button.setVisibility( View.VISIBLE );
} }
public void setSelCB( SelectableItem selCB )
{
m_selCb = selCB;
}
public void setSelected( boolean selected )
{
if ( selected != m_selected ) {
toggleSelected();
}
}
@Override @Override
public void setEnabled( boolean enabled ) public void setEnabled( boolean enabled )
{ {
@ -105,4 +123,21 @@ public class XWListItem extends LinearLayout {
return m_cached; return m_cached;
} }
// SelectableItem.LongClickHandler interface
public void longClicked()
{
toggleSelected();
}
private void toggleSelected()
{
m_selected = !m_selected;
if ( m_selected ) {
m_origDrawable = getBackground();
setBackgroundColor( XWApp.SEL_COLOR );
} else {
setBackgroundDrawable( m_origDrawable );
}
m_selCb.itemToggled( this, m_selected );
}
} }