break the last Activities out into Delegates, and move a bunch of

stuff info the delegate base class so fewer calls required on
m_activity and LocUtils.
This commit is contained in:
Eric House 2014-05-06 05:56:43 -07:00
parent 5d9e846316
commit d566bd63ae
19 changed files with 842 additions and 833 deletions

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2009-2011 by Eric House (xwords@eehouse.org). All
* Copyright 2009-2014 by Eric House (xwords@eehouse.org). All
* rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -20,152 +20,17 @@
package org.eehouse.android.xw4;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.TextView;
import android.os.Handler;
import junit.framework.Assert;
public class BTInviteActivity extends InviteActivity {
import org.eehouse.android.xw4.loc.LocUtils;
public class BTInviteActivity extends InviteActivity
implements CompoundButton.OnCheckedChangeListener {
private boolean m_firstScan;
private int m_checkCount;
public static void launchForResult( Activity activity, int nMissing,
int requestCode )
{
Intent intent = new Intent( activity, BTInviteActivity.class );
intent.putExtra( INTENT_KEY_NMISSING, nMissing );
activity.startActivityForResult( intent, requestCode );
}
private BTInviteDelegate m_dlgt;
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState, R.layout.btinviter,
R.id.button_invite, R.id.button_rescan,
R.id.button_clear, R.id.invite_desc,
R.string.invite_bt_desc_fmt );
tryEnable();
m_firstScan = true;
BTService.clearDevices( this, null ); // will return names
super.onCreate( savedInstanceState );
m_dlgt = new BTInviteDelegate( this, savedInstanceState );
m_dlgt.init();
}
// MultiService.MultiEventListener interface
@Override
public void eventOccurred( MultiService.MultiEvent event, final Object ... args )
{
switch( event ) {
case SCAN_DONE:
post( new Runnable() {
public void run() {
synchronized( BTInviteActivity.this ) {
stopProgress();
String[] btDevNames = null;
if ( 0 < args.length ) {
btDevNames = (String[])(args[0]);
if ( null != btDevNames
&& 0 == btDevNames.length ) {
btDevNames = null;
}
}
if ( null == btDevNames && m_firstScan ) {
BTService.scan( BTInviteActivity.this );
}
setListAdapter( new BTDevsAdapter( btDevNames ) );
m_checkCount = 0;
tryEnable();
m_firstScan = false;
}
}
} );
break;
default:
super.eventOccurred( event, args );
}
}
protected void scan()
{
startProgress( R.string.scan_progress );
BTService.scan( this );
}
protected void clearSelected()
{
BTService.clearDevices( this, listSelected() );
}
protected String[] listSelected()
{
ListView list = (ListView)findViewById( android.R.id.list );
String[] result = new String[m_checkCount];
int count = list.getChildCount();
int index = 0;
for ( int ii = 0; ii < count; ++ii ) {
CheckBox box = (CheckBox)list.getChildAt( ii );
if ( box.isChecked() ) {
result[index++] = box.getText().toString();
}
}
return result;
}
protected void tryEnable()
{
m_okButton.setEnabled( m_checkCount == m_nMissing );
m_clearButton.setEnabled( 0 < m_checkCount );
}
public void onCheckedChanged( CompoundButton buttonView,
boolean isChecked )
{
if ( isChecked ) {
++m_checkCount;
} else {
--m_checkCount;
}
DbgUtils.logf( "BTInviteActivity.onCheckedChanged( isChecked=%b ); "
+ "count now %d", isChecked, m_checkCount );
tryEnable();
}
private class BTDevsAdapter extends XWListAdapter {
private String[] m_devs;
public BTDevsAdapter( String[] devs )
{
super( null == devs? 0 : devs.length );
m_devs = devs;
}
public Object getItem( int position) { return m_devs[position]; }
public View getView( final int position, View convertView,
ViewGroup parent ) {
CheckBox box = (CheckBox)
LocUtils.inflate( BTInviteActivity.this, R.layout.btinviter_item );
box.setText( m_devs[position] );
box.setOnCheckedChangeListener( BTInviteActivity.this );
return box;
}
}
}

View file

@ -0,0 +1,172 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2009-2011 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 android.app.Activity;
import android.app.ListActivity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.TextView;
import android.os.Handler;
import junit.framework.Assert;
public class BTInviteDelegate extends InviteDelegate
implements CompoundButton.OnCheckedChangeListener {
private ListActivity m_activity;
private boolean m_firstScan;
private int m_checkCount;
public static void launchForResult( Activity activity, int nMissing,
int requestCode )
{
Intent intent = new Intent( activity, BTInviteActivity.class );
intent.putExtra( INTENT_KEY_NMISSING, nMissing );
activity.startActivityForResult( intent, requestCode );
}
protected BTInviteDelegate( ListActivity activity, Bundle savedInstanceState )
{
super( activity, savedInstanceState );
m_activity = activity;
}
protected void init()
{
super.init( R.layout.btinviter,
R.id.button_invite, R.id.button_rescan,
R.id.button_clear, R.id.invite_desc,
R.string.invite_bt_desc_fmt );
m_firstScan = true;
BTService.clearDevices( m_activity, null ); // will return names
}
// MultiService.MultiEventListener interface
@Override
public void eventOccurred( MultiService.MultiEvent event, final Object ... args )
{
switch( event ) {
case SCAN_DONE:
post( new Runnable() {
public void run() {
synchronized( BTInviteDelegate.this ) {
stopProgress();
String[] btDevNames = null;
if ( 0 < args.length ) {
btDevNames = (String[])(args[0]);
if ( null != btDevNames
&& 0 == btDevNames.length ) {
btDevNames = null;
}
}
if ( null == btDevNames && m_firstScan ) {
BTService.scan( m_activity );
}
setListAdapter( new BTDevsAdapter( btDevNames ) );
m_checkCount = 0;
tryEnable();
m_firstScan = false;
}
}
} );
break;
default:
super.eventOccurred( event, args );
}
}
protected void scan()
{
startProgress( R.string.scan_progress );
BTService.scan( m_activity );
}
protected void clearSelected()
{
BTService.clearDevices( m_activity, listSelected() );
}
protected String[] listSelected()
{
ListView list = (ListView)findViewById( android.R.id.list );
String[] result = new String[m_checkCount];
int count = list.getChildCount();
int index = 0;
for ( int ii = 0; ii < count; ++ii ) {
CheckBox box = (CheckBox)list.getChildAt( ii );
if ( box.isChecked() ) {
result[index++] = box.getText().toString();
}
}
return result;
}
protected void tryEnable()
{
m_okButton.setEnabled( m_checkCount == m_nMissing );
m_clearButton.setEnabled( 0 < m_checkCount );
}
public void onCheckedChanged( CompoundButton buttonView,
boolean isChecked )
{
if ( isChecked ) {
++m_checkCount;
} else {
--m_checkCount;
}
DbgUtils.logf( "BTInviteActivity.onCheckedChanged( isChecked=%b ); "
+ "count now %d", isChecked, m_checkCount );
tryEnable();
}
private class BTDevsAdapter extends XWListAdapter {
private String[] m_devs;
public BTDevsAdapter( String[] devs )
{
super( null == devs? 0 : devs.length );
m_devs = devs;
}
public Object getItem( int position) { return m_devs[position]; }
public View getView( final int position, View convertView,
ViewGroup parent ) {
CheckBox box = (CheckBox)inflate( R.layout.btinviter_item );
box.setText( m_devs[position] );
box.setOnCheckedChangeListener( BTInviteDelegate.this );
return box;
}
}
}

View file

@ -62,7 +62,6 @@ import org.eehouse.android.xw4.jni.*;
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
import org.eehouse.android.xw4.jni.JNIThread.*;
import org.eehouse.android.xw4.loc.LocUtils;
public class BoardDelegate extends DelegateBase
implements TransportProcs.TPMsgHandler, View.OnClickListener,
@ -400,7 +399,7 @@ public class BoardDelegate extends DelegateBase
public void onClick( DialogInterface dialog,
int whichButton ) {
m_resultCode = UtilCtxt.PICKER_BACKUP;
m_activity.removeDialog( dlgID.ordinal() );
removeDialog( dlgID );
}
};
ab.setPositiveButton( R.string.tilepick_undo,
@ -411,7 +410,7 @@ public class BoardDelegate extends DelegateBase
public void onClick( DialogInterface dialog,
int whichButton ) {
m_resultCode = UtilCtxt.PICKER_PICKALL;
m_activity.removeDialog( dlgID.ordinal() );
removeDialog( dlgID );
}
};
ab.setNegativeButton( R.string.tilepick_all, doAllClicked );
@ -603,12 +602,12 @@ public class BoardDelegate extends DelegateBase
case BT_INVITE_RESULT:
// onActivityResult is called immediately *before*
// onResume -- meaning m_gi etc are still null.
m_missingDevs = data.getStringArrayExtra( BTInviteActivity.DEVS );
m_missingDevs = data.getStringArrayExtra( BTInviteDelegate.DEVS );
break;
case SMS_INVITE_RESULT:
// onActivityResult is called immediately *before*
// onResume -- meaning m_gi etc are still null.
m_missingDevs = data.getStringArrayExtra( SMSInviteActivity.DEVS );
m_missingDevs = data.getStringArrayExtra( SMSInviteDelegate.DEVS );
break;
}
}
@ -913,11 +912,11 @@ public class BoardDelegate extends DelegateBase
doSyncMenuitem();
break;
case BT_PICK_ACTION:
BTInviteActivity.launchForResult( m_activity, m_nMissingPlayers,
BTInviteDelegate.launchForResult( m_activity, m_nMissingPlayers,
BT_INVITE_RESULT );
break;
case SMS_PICK_ACTION:
SMSInviteActivity.launchForResult( m_activity, m_nMissingPlayers,
SMSInviteDelegate.launchForResult( m_activity, m_nMissingPlayers,
SMS_INVITE_RESULT );
break;
case SMS_CONFIG_ACTION:
@ -1728,8 +1727,7 @@ public class BoardDelegate extends DelegateBase
m_dlgTitle = R.string.badwords_title;
waitBlockingDialog( DlgID.DLG_BADWORDS_BLK, 0 );
} else {
m_dlgBytes = message +
LocUtils.getString( m_activity, R.string.badwords_accept );
m_dlgBytes = message + getString( R.string.badwords_accept );
m_dlgTitle = R.string.query_title;
accept = 0 != waitBlockingDialog( DlgID.QUERY_REQUEST_BLK, 0 );
}
@ -1953,7 +1951,7 @@ public class BoardDelegate extends DelegateBase
return new OnDismissListener() {
public void onDismiss( DialogInterface di ) {
releaseIfBlocking();
m_activity.removeDialog( id );
removeDialog( id );
}
};
}
@ -2229,8 +2227,7 @@ public class BoardDelegate extends DelegateBase
private void setupPasswdVars()
{
m_dlgTitleStr = getString( R.string.msg_ask_password_fmt, m_pwdName );
m_passwdLyt = (LinearLayout)LocUtils.inflate( m_activity,
R.layout.passwd_view );
m_passwdLyt = (LinearLayout)inflate( R.layout.passwd_view );
m_passwdEdit = (EditText)m_passwdLyt.findViewById( R.id.edit );
}

View file

@ -32,8 +32,6 @@ import android.view.MenuItem;
import android.view.MenuInflater;
import android.widget.LinearLayout;
import org.eehouse.android.xw4.loc.LocUtils;
public class ChatDelegate extends DelegateBase
implements View.OnClickListener {
@ -59,9 +57,9 @@ public class ChatDelegate extends DelegateBase
for ( DBUtils.HistoryPair pair : pairs ) {
TextView view = (TextView)
LocUtils.inflate( m_activity, pair.sourceLocal
? R.layout.chat_history_local
: R.layout.chat_history_remote );
inflate( pair.sourceLocal
? R.layout.chat_history_local
: R.layout.chat_history_remote );
view.setText( pair.msg );
layout.addView( view );
}
@ -96,13 +94,13 @@ public class ChatDelegate extends DelegateBase
EditText edit = (EditText)findViewById( R.id.chat_edit );
String text = edit.getText().toString();
if ( null == text || text.length() == 0 ) {
m_activity.setResult( Activity.RESULT_CANCELED );
setResult( Activity.RESULT_CANCELED );
} else {
DBUtils.appendChatHistory( m_activity, m_rowid, text, true );
Intent result = new Intent();
result.putExtra( BoardDelegate.INTENT_KEY_CHAT, text );
m_activity.setResult( Activity.RESULT_OK, result );
setResult( Activity.RESULT_OK, result );
}
finish();
}

View file

@ -97,6 +97,21 @@ public class DelegateBase implements DlgDelegate.DlgClickNotify,
m_activity.startActivityForResult( intent, requestCode );
}
protected void setResult( int result, Intent intent )
{
m_activity.setResult( result, intent );
}
protected void setResult( int result )
{
m_activity.setResult( result );
}
protected void onContentChanged()
{
m_activity.onContentChanged();
}
protected void startActivity( Intent intent )
{
m_activity.startActivity( intent );
@ -112,6 +127,11 @@ public class DelegateBase implements DlgDelegate.DlgClickNotify,
return LocUtils.getString( m_activity, resID, params );
}
protected String[] getStringArray( int resID )
{
return LocUtils.getStringArray( m_activity, resID );
}
protected View inflate( int resID )
{
return LocUtils.inflate( m_activity, resID );
@ -122,6 +142,16 @@ public class DelegateBase implements DlgDelegate.DlgClickNotify,
m_delegate.showDialog( dlgID );
}
protected void removeDialog( DlgID dlgID )
{
removeDialog( dlgID.ordinal() );
}
protected void removeDialog( int id )
{
m_activity.removeDialog( id );
}
protected Dialog onCreateDialog( int id )
{
return m_delegate.createDialog( id );

View file

@ -46,9 +46,8 @@ import junit.framework.Assert;
import org.eehouse.android.xw4.DlgDelegate.Action;
import org.eehouse.android.xw4.jni.JNIUtilsImpl;
import org.eehouse.android.xw4.jni.XwJNI;
import org.eehouse.android.xw4.loc.LocUtils;
public class DictBrowseDelegate extends DelegateBase
public class DictBrowseDelegate extends ListDelegateBase
implements View.OnClickListener, OnItemSelectedListener {
private static final String DICT_NAME = "DICT_NAME";
@ -91,9 +90,9 @@ public class DictBrowseDelegate extends DelegateBase
int format = m_browseState.m_minShown == m_browseState.m_maxShown ?
R.string.dict_browse_title1_fmt : R.string.dict_browse_title_fmt;
setTitle( LocUtils.getString( m_activity, format,
m_name, m_nWords, m_browseState.m_minShown,
m_browseState.m_maxShown ));
setTitle( getString( format,
m_name, m_nWords, m_browseState.m_minShown,
m_browseState.m_maxShown ));
String desc = XwJNI.dict_iter_getDesc( m_dictClosure );
if ( null != desc ) {
@ -107,8 +106,7 @@ public class DictBrowseDelegate extends DelegateBase
public Object getItem( int position )
{
TextView text = (TextView)
LocUtils.inflate( m_activity,
android.R.layout.simple_list_item_1 );
inflate( android.R.layout.simple_list_item_1 );
String str = XwJNI.dict_iter_nthWord( m_dictClosure, position );
if ( null != str ) {
text.setText( str );
@ -198,8 +196,7 @@ public class DictBrowseDelegate extends DelegateBase
// this is extended to include tile info -- it should
// be -- then use an empty list elem and disable
// search/minmax stuff.
String msg = LocUtils.getString( m_activity, R.string.alert_empty_dict_fmt,
name );
String msg = getString( R.string.alert_empty_dict_fmt, name );
showOKOnlyDialogThen( msg, Action.FINISH_ACTION );
} else {
figureMinMax( m_browseState.m_counts );
@ -220,9 +217,9 @@ public class DictBrowseDelegate extends DelegateBase
setUpSpinners();
m_activity.setListAdapter( new DictListAdapter() );
m_activity.getListView().setFastScrollEnabled( true );
m_activity.getListView().setSelectionFromTop( m_browseState.m_pos,
setListAdapter( new DictListAdapter() );
getListView().setFastScrollEnabled( true );
getListView().setSelectionFromTop( m_browseState.m_pos,
m_browseState.m_top );
}
}
@ -231,7 +228,7 @@ public class DictBrowseDelegate extends DelegateBase
protected void onPause()
{
if ( null != m_browseState ) { // already saved?
ListView list = m_activity.getListView();
ListView list = getListView();
m_browseState.m_pos = list.getFirstVisiblePosition();
View view = list.getChildAt( 0 );
m_browseState.m_top = (view == null) ? 0 : view.getTop();
@ -339,7 +336,7 @@ public class DictBrowseDelegate extends DelegateBase
if ( null != text && 0 < text.length() ) {
int pos = XwJNI.dict_iter_getStartsWith( m_dictClosure, text );
if ( 0 <= pos ) {
m_activity.getListView().setSelection( pos );
getListView().setSelection( pos );
} else {
DbgUtils.showf( m_activity, R.string.dict_browse_nowords_fmt,
m_name, text );

View file

@ -40,8 +40,6 @@ import java.net.URLConnection;
import java.security.MessageDigest;
import java.util.HashMap;
import org.eehouse.android.xw4.loc.LocUtils;
import junit.framework.Assert;
public class DictImportDelegate extends DelegateBase {

View file

@ -60,7 +60,6 @@ import org.eehouse.android.xw4.jni.XwJNI;
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.loc.LocUtils;
public class DictsDelegate extends DelegateBase
implements View.OnClickListener, AdapterView.OnItemLongClickListener,
@ -186,8 +185,7 @@ public class DictsDelegate extends DelegateBase
public View getGroupView( int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent )
{
View row = LocUtils.inflate( m_activity, android.R.layout
.simple_expandable_list_item_1 );
View row = inflate( android.R.layout.simple_expandable_list_item_1 );
TextView view = (TextView)row.findViewById( android.R.id.text1 );
view.setText( m_langs[groupPosition] );
return view;
@ -374,7 +372,7 @@ public class DictsDelegate extends DelegateBase
}
}
m_locNames = LocUtils.getStringArray( m_activity, R.array.loc_names );
m_locNames = getStringArray( R.array.loc_names );
m_downloadStr = getString( R.string.download_dicts );

View file

@ -57,7 +57,6 @@ import org.eehouse.android.xw4.DlgDelegate.Action;
import org.eehouse.android.xw4.jni.*;
import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
import org.eehouse.android.xw4.loc.LocUtils;
public class GameConfigDelegate extends DelegateBase
implements View.OnClickListener
@ -629,7 +628,7 @@ public class GameConfigDelegate extends DelegateBase
saveChanges();
if ( m_forResult ) {
applyChanges( true );
m_activity.setResult( Activity.RESULT_OK, null );
setResult( Activity.RESULT_OK, null );
finish();
} else if ( !m_gameStarted ) { // no confirm needed
applyChanges( true );

View file

@ -57,9 +57,8 @@ import junit.framework.Assert;
import org.eehouse.android.xw4.DlgDelegate.Action;
import org.eehouse.android.xw4.jni.*;
import org.eehouse.android.xw4.loc.LocUtils;
public class GamesListDelegate extends DelegateBase
public class GamesListDelegate extends ListDelegateBase
implements OnItemLongClickListener,
DBUtils.DBChangeListener, SelectableItem,
DictImportDelegate.DownloadFinishedListener,
@ -239,7 +238,7 @@ public class GamesListDelegate extends DelegateBase
DBUtils.setGroupName( m_activity,
m_groupid, name );
m_adapter.inval( m_rowid );
m_activity.onContentChanged();
onContentChanged();
}
};
dialog = buildNamerDlg( m_adapter.groupName( m_groupid ),
@ -254,7 +253,7 @@ public class GamesListDelegate extends DelegateBase
String name = m_namer.getName();
DBUtils.addGroup( m_activity, name );
// m_adapter.inval();
m_activity.onContentChanged();
onContentChanged();
}
};
dialog = buildNamerDlg( "", R.string.newgroup_label,
@ -289,7 +288,7 @@ public class GamesListDelegate extends DelegateBase
DBUtils.moveGame( m_activity, rowid, gid );
}
DBUtils.setGroupExpanded( m_activity, gid, true );
m_activity.onContentChanged();
onContentChanged();
}
};
String[] groups = m_adapter.groupNames();
@ -304,8 +303,7 @@ public class GamesListDelegate extends DelegateBase
break;
case GET_NAME:
layout =
(LinearLayout)LocUtils.inflate( m_activity, R.layout.dflt_name );
layout = (LinearLayout)inflate( R.layout.dflt_name );
final EditText etext =
(EditText)layout.findViewById( R.id.name_edit );
etext.setText( CommonPrefs.getDefaultPlayerName( m_activity,
@ -356,7 +354,7 @@ public class GamesListDelegate extends DelegateBase
getBundledData( savedInstanceState );
setContentView( R.layout.game_list );
ListView listview = m_activity.getListView();
ListView listview = getListView();
DBUtils.setDBChangeListener( this );
boolean isUpgrade = Utils.firstBootThisVersion( m_activity );
@ -458,7 +456,7 @@ public class GamesListDelegate extends DelegateBase
m_activity.runOnUiThread( new Runnable() {
public void run() {
if ( countChanged || DBUtils.ROWID_NOTFOUND == rowid ) {
m_activity.onContentChanged();
onContentChanged();
if ( DBUtils.ROWID_NOTFOUND != rowid ) {
m_launchedGame = rowid;
}
@ -562,7 +560,7 @@ public class GamesListDelegate extends DelegateBase
for ( long rowid : rowids ) {
GameUtils.resetGame( m_activity, rowid );
}
m_activity.onContentChanged(); // required because position may change
onContentChanged(); // required because position may change
break;
case SYNC_MENU:
doSyncMenuitem();
@ -582,7 +580,7 @@ public class GamesListDelegate extends DelegateBase
GameUtils.deleteGroup( m_activity, groupID );
}
clearSelections();
m_activity.onContentChanged();
onContentChanged();
break;
case DELETE_GAMES:
deleteGames( (long[])params[0] );
@ -602,7 +600,7 @@ public class GamesListDelegate extends DelegateBase
protected void contentChanged()
{
if ( null != m_adapter ) {
m_adapter.expandGroups( m_activity.getListView() );
m_adapter.expandGroups( getListView() );
}
}
@ -821,7 +819,7 @@ public class GamesListDelegate extends DelegateBase
DBUtils.saveSummary( self, lock, smry );
m_selGames.add( lock.getRowid() );
lock.unlock();
m_activity.onContentChanged();
onContentChanged();
}
});
}
@ -884,7 +882,7 @@ public class GamesListDelegate extends DelegateBase
clearSelections();
}
if ( changeContent ) {
m_activity.onContentChanged();
onContentChanged();
}
return handled;// || super.onOptionsItemSelected( item );
@ -1147,7 +1145,7 @@ public class GamesListDelegate extends DelegateBase
if ( m_adapter.setField( newField ) ) {
// The adapter should be able to decide whether full
// content change is required. PENDING
m_activity.onContentChanged();
onContentChanged();
}
}
@ -1155,8 +1153,7 @@ public class GamesListDelegate extends DelegateBase
DialogInterface.OnClickListener lstnr,
DlgID dlgID )
{
m_namer = (GameNamer)
LocUtils.inflate( m_activity, R.layout.rename_game );
m_namer = (GameNamer)inflate( R.layout.rename_game );
m_namer.setName( curname );
m_namer.setLabel( labelID );
Dialog dialog = makeAlertBuilder()
@ -1343,13 +1340,13 @@ public class GamesListDelegate extends DelegateBase
private GameListAdapter makeNewAdapter()
{
ListView listview = m_activity.getListView();
ListView listview = getListView();
String field = CommonPrefs.getSummaryField( m_activity );
long[] positions = XWPrefs.getGroupPositions( m_activity );
GameListAdapter adapter =
new GameListAdapter( m_activity, listview, new Handler(),
this, positions, field );
m_activity.setListAdapter( adapter );
setListAdapter( adapter );
adapter.expandGroups( listview );
return adapter;
}

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2009-2011 by Eric House (xwords@eehouse.org). All
* Copyright 2009-2014 by Eric House (xwords@eehouse.org). All
* rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -20,81 +20,17 @@
package org.eehouse.android.xw4;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.app.ListActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import org.eehouse.android.xw4.loc.LocUtils;
public class InviteActivity extends ListActivity {
import junit.framework.Assert;
abstract class InviteActivity extends XWListActivity
implements View.OnClickListener {
public static final String DEVS = "DEVS";
protected static final String INTENT_KEY_NMISSING = "NMISSING";
protected int m_nMissing;
protected Button m_okButton;
protected Button m_rescanButton;
protected Button m_clearButton;
protected void onCreate( Bundle savedInstanceState, int view_id,
int button_invite, int button_rescan,
int button_clear, int desc_id, int desc_strf )
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
requestWindowFeature( Window.FEATURE_NO_TITLE );
setContentView( view_id );
Intent intent = getIntent();
m_nMissing = intent.getIntExtra( INTENT_KEY_NMISSING, -1 );
m_okButton = (Button)findViewById( button_invite );
m_okButton.setOnClickListener( this );
m_rescanButton = (Button)findViewById( button_rescan );
m_rescanButton.setOnClickListener( this );
m_clearButton = (Button)findViewById( button_clear );
m_clearButton.setOnClickListener( this );
TextView desc = (TextView)findViewById( desc_id );
desc.setText( LocUtils.getString( this, desc_strf, m_nMissing ) );
tryEnable();
}
public void onClick( View view )
{
if ( m_okButton == view ) {
Intent intent = new Intent();
String[] devs = listSelected();
intent.putExtra( DEVS, devs );
setResult( Activity.RESULT_OK, intent );
finish();
} else if ( m_rescanButton == view ) {
scan();
} else if ( m_clearButton == view ) {
clearSelected();
}
}
abstract void tryEnable() ;
abstract String[] listSelected();
abstract void scan();
abstract void clearSelected();
}

View file

@ -0,0 +1,93 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2009-2014 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 android.app.Activity;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import junit.framework.Assert;
abstract class InviteDelegate extends ListDelegateBase
implements View.OnClickListener {
public static final String DEVS = "DEVS";
protected static final String INTENT_KEY_NMISSING = "NMISSING";
protected int m_nMissing;
protected Button m_okButton;
protected Button m_rescanButton;
protected Button m_clearButton;
private ListActivity m_activity;
public InviteDelegate( ListActivity activity, Bundle savedInstanceState )
{
super( activity, savedInstanceState );
m_activity = activity;
}
protected void init( int view_id, int button_invite, int button_rescan,
int button_clear, int desc_id, int desc_strf )
{
setContentView( view_id );
Intent intent = getIntent();
m_nMissing = intent.getIntExtra( INTENT_KEY_NMISSING, -1 );
m_okButton = (Button)findViewById( button_invite );
m_okButton.setOnClickListener( this );
m_rescanButton = (Button)findViewById( button_rescan );
m_rescanButton.setOnClickListener( this );
m_clearButton = (Button)findViewById( button_clear );
m_clearButton.setOnClickListener( this );
TextView desc = (TextView)findViewById( desc_id );
desc.setText( getString( desc_strf, m_nMissing ) );
tryEnable();
}
public void onClick( View view )
{
if ( m_okButton == view ) {
Intent intent = new Intent();
String[] devs = listSelected();
intent.putExtra( DEVS, devs );
setResult( Activity.RESULT_OK, intent );
finish();
} else if ( m_rescanButton == view ) {
scan();
} else if ( m_clearButton == view ) {
clearSelected();
}
}
abstract void tryEnable() ;
abstract String[] listSelected();
abstract void scan();
abstract void clearSelected();
}

View file

@ -0,0 +1,57 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2014 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 android.app.ListActivity;
import android.os.Bundle;
import android.widget.ListAdapter;
import android.widget.ListView;
public class ListDelegateBase extends DelegateBase {
private ListActivity m_activity;
protected ListDelegateBase( ListActivity activity, Bundle savedInstanceState,
int menuID )
{
super( activity, savedInstanceState, menuID );
m_activity = activity;
}
protected ListDelegateBase( ListActivity activity, Bundle savedState )
{
this( activity, savedState, 0);
}
protected void setListAdapter( ListAdapter adapter )
{
m_activity.setListAdapter( adapter );
}
protected ListAdapter setListAdapter()
{
return m_activity.getListAdapter();
}
protected ListView getListView()
{
return m_activity.getListView();
}
}

View file

@ -42,7 +42,6 @@ import org.eehouse.android.xw4.jni.CurGameInfo;
import org.eehouse.android.xw4.jni.CommonPrefs;
import org.eehouse.android.xw4.jni.CommsAddrRec;
import org.eehouse.android.xw4.jni.XwJNI;
import org.eehouse.android.xw4.loc.LocUtils;
public class NewGameDelegate extends DelegateBase {
@ -188,7 +187,7 @@ public class NewGameDelegate extends DelegateBase {
if ( Activity.RESULT_CANCELED != resultCode ) {
m_nameForBT = INVITE_FOR_BT == requestCode;
String[] remoteDevs =
data.getStringArrayExtra( InviteActivity.DEVS );
data.getStringArrayExtra( InviteDelegate.DEVS );
Assert.assertTrue( 1 == remoteDevs.length );
m_remoteDev = remoteDevs[0];
@ -208,8 +207,7 @@ public class NewGameDelegate extends DelegateBase {
DlgID dlgID = DlgID.values()[id];
switch( dlgID ) {
case NAME_GAME:
final GameNamer namerView =
(GameNamer)LocUtils.inflate( m_activity, R.layout.rename_game );
final GameNamer namerView = (GameNamer)inflate( R.layout.rename_game );
namerView.setLabel( m_nameForBT ? R.string.btname_label
: R.string.smsname_label );
namerView.setName( m_gameName );
@ -360,7 +358,7 @@ public class NewGameDelegate extends DelegateBase {
intent.putExtra( GameUtils.INTENT_FORRESULT_ROWID, true );
startActivityForResult( intent, CONFIG_FOR_BT );
} else {
BTInviteActivity.launchForResult( m_activity, 1, INVITE_FOR_BT );
BTInviteDelegate.launchForResult( m_activity, 1, INVITE_FOR_BT );
}
}
}
@ -381,7 +379,7 @@ public class NewGameDelegate extends DelegateBase {
intent.putExtra( GameUtils.INTENT_FORRESULT_ROWID, true );
startActivityForResult( intent, CONFIG_FOR_SMS );
} else {
SMSInviteActivity.launchForResult( m_activity, 1, INVITE_FOR_SMS );
SMSInviteDelegate.launchForResult( m_activity, 1, INVITE_FOR_SMS );
}
}

View file

@ -107,7 +107,7 @@ public class PrefsDelegate extends DelegateBase
dialog = SMSCheckBoxPreference.onCreateDialog( m_activity, id );
break;
case EXPLAIN_TITLE:
dialog = LocUtils.makeAlertBuilder( m_activity )
dialog = makeAlertBuilder()
.setMessage( R.string.no_hide_titlebar )
.setTitle( R.string.info_title )
.setPositiveButton( R.string.button_ok, null )
@ -116,7 +116,7 @@ public class PrefsDelegate extends DelegateBase
}
if ( null == dialog && null != lstnr ) {
dialog = LocUtils.makeAlertBuilder( m_activity )
dialog = makeAlertBuilder()
.setTitle( R.string.query_title )
.setMessage( confirmID )
.setPositiveButton( R.string.button_ok, lstnr )

View file

@ -21,398 +21,44 @@
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 android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract;
import android.text.method.DialerKeyListener;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import org.eehouse.android.xw4.DlgDelegate.Action;
import org.eehouse.android.xw4.loc.LocUtils;
public class SMSInviteActivity extends InviteActivity {
private static final int GET_CONTACT = 1;
private static final String SAVE_NAME = "SAVE_NAME";
private static final String SAVE_NUMBER = "SAVE_NUMBER";
private ArrayList<PhoneRec> m_phoneRecs;
private SMSPhonesAdapter m_adapter;
private ImageButton m_addButton;
private String m_pendingName;
private String m_pendingNumber;
private boolean m_immobileConfirmed;
public static void launchForResult( Activity activity, int nMissing,
int requestCode )
{
Intent intent = new Intent( activity, SMSInviteActivity.class );
intent.putExtra( INTENT_KEY_NMISSING, nMissing );
activity.startActivityForResult( intent, requestCode );
}
private SMSInviteDelegate m_dlgt;
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState, R.layout.smsinviter,
R.id.button_invite, R.id.button_add,
R.id.button_clear, R.id.invite_desc,
R.string.invite_sms_desc_fmt );
getBundledData( savedInstanceState );
m_addButton = (ImageButton)findViewById( R.id.manual_add_button );
m_addButton.setOnClickListener( new View.OnClickListener() {
public void onClick( View view )
{
showDialog( DlgID.GET_NUMBER.ordinal() );
}
} );
getSavedState();
rebuildList( true );
super.onCreate( savedInstanceState );
m_dlgt = new SMSInviteDelegate( this, savedInstanceState );
m_dlgt.init( savedInstanceState );
}
@Override
protected void onSaveInstanceState( Bundle outState )
{
super.onSaveInstanceState( outState );
outState.putString( SAVE_NAME, m_pendingName );
outState.putString( SAVE_NUMBER, m_pendingNumber );
m_dlgt.onSaveInstanceState( outState );
}
private void getBundledData( Bundle bundle )
{
if ( null != bundle ) {
m_pendingName = bundle.getString( SAVE_NAME );
m_pendingNumber = bundle.getString( SAVE_NUMBER );
}
}
@Override
protected void onActivityResult( int requestCode, int resultCode,
Intent data )
{
super.onActivityResult(requestCode, resultCode, data);
if ( Activity.RESULT_CANCELED != resultCode && data != null ) {
switch (requestCode) {
case GET_CONTACT:
addPhoneNumbers( data );
break;
}
}
super.onActivityResult( requestCode, resultCode, data );
m_dlgt.onActivityResult( requestCode, resultCode, data );
}
@Override
protected Dialog onCreateDialog( int id )
{
{
Dialog dialog = super.onCreateDialog( id );
if ( null == dialog ) {
DialogInterface.OnClickListener lstnr;
DlgID dlgID = DlgID.values()[id];
switch( dlgID ) {
case GET_NUMBER:
final GameNamer namerView =
(GameNamer)LocUtils.inflate( this, R.layout.rename_game );
namerView.setLabel( R.string.get_sms_number );
namerView.setKeyListener(DialerKeyListener.getInstance());
lstnr = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int item ) {
String number = namerView.getName();
PhoneRec rec = new PhoneRec( number );
m_pendingNumber = number;
m_pendingName = null;
showConfirmThen( R.string.warn_unlimited,
R.string.button_yes,
Action.POST_WARNING_ACTION );
}
};
dialog = new AlertDialog.Builder( this )
.setNegativeButton( R.string.button_cancel, null )
.setPositiveButton( R.string.button_ok, lstnr )
.setView( namerView )
.create();
break;
}
Utils.setRemoveOnDismiss( this, dialog, dlgID );
dialog = m_dlgt.onCreateDialog( id );
}
return dialog;
}
protected void scan()
{
Intent intent = new Intent( Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI );
intent.setType( Phone.CONTENT_TYPE );
startActivityForResult( intent, GET_CONTACT );
}
protected void clearSelected()
{
showConfirmThen( R.string.confirm_clear, Action.CLEAR_ACTION );
}
protected String[] listSelected()
{
int count = m_adapter.getCount();
String[] result = new String[countChecks()];
int index = 0;
Iterator<PhoneRec> iter = m_phoneRecs.iterator();
for ( int ii = 0; iter.hasNext(); ++ii ) {
if ( iter.next().m_checked ) {
result[index++] =
((SMSListItem)m_adapter.getItem(ii)).getNumber();
}
}
return result;
}
@Override
protected void tryEnable()
{
int count = countChecks();
m_okButton.setEnabled( count == m_nMissing );
m_clearButton.setEnabled( 0 < count );
}
// DlgDelegate.DlgClickNotify interface
@Override
public void dlgButtonClicked( Action action, int which, Object[] params )
{
switch( which ) {
case AlertDialog.BUTTON_POSITIVE:
switch( action ) {
case CLEAR_ACTION:
clearSelectedImpl();
break;
case USE_IMMOBILE_ACTION:
m_immobileConfirmed = true;
break;
case POST_WARNING_ACTION:
addChecked( new PhoneRec( m_pendingName, m_pendingNumber ) );
saveAndRebuild();
break;
}
break;
case DlgDelegate.DISMISS_BUTTON:
if ( Action.USE_IMMOBILE_ACTION == action && m_immobileConfirmed ) {
showConfirmThen( R.string.warn_unlimited,
R.string.button_yes,
Action.POST_WARNING_ACTION );
}
break;
}
}
private int countChecks()
{
int count = 0;
if ( null != m_phoneRecs ) {
Iterator<PhoneRec> iter = m_phoneRecs.iterator();
while ( iter.hasNext() ) {
if ( iter.next().m_checked ) {
++count;
}
}
}
return count;
}
private void addPhoneNumbers( Intent intent )
{
Uri data = intent.getData();
Cursor cursor = managedQuery( data,
new String[] { Phone.DISPLAY_NAME,
Phone.NUMBER,
Phone.TYPE },
null, null, null );
// Have seen a crash reporting
// "android.database.StaleDataException: Attempted to access a
// cursor after it has been closed." when the query takes a
// long time to return. Be safe.
if ( null != cursor && !cursor.isClosed() ) {
if ( cursor.moveToFirst() ) {
String name =
cursor.getString( cursor.
getColumnIndex( Phone.DISPLAY_NAME));
String number =
cursor.getString( cursor.
getColumnIndex( Phone.NUMBER ) );
int type = cursor.getInt( cursor.
getColumnIndex( Phone.TYPE ) );
m_pendingName = name;
m_pendingNumber = number;
if ( Phone.TYPE_MOBILE == type ) {
showConfirmThen( R.string.warn_unlimited,
R.string.button_yes,
Action.POST_WARNING_ACTION );
} else {
m_immobileConfirmed = false;
String msg =
LocUtils.getString( this, R.string.warn_nomobile_fmt,
number, name );
showConfirmThen( msg, R.string.button_yes,
Action.USE_IMMOBILE_ACTION );
}
}
}
} // addPhoneNumbers
private void rebuildList( boolean checkIfAll )
{
Collections.sort( m_phoneRecs, new Comparator<PhoneRec>() {
public int compare( PhoneRec rec1, PhoneRec rec2 ) {
return rec1.m_name.compareTo(rec2.m_name);
}
});
m_adapter = new SMSPhonesAdapter();
setListAdapter( m_adapter );
if ( checkIfAll && m_phoneRecs.size() <= m_nMissing ) {
Iterator<PhoneRec> iter = m_phoneRecs.iterator();
while ( iter.hasNext() ) {
iter.next().m_checked = true;
}
}
tryEnable();
}
private void getSavedState()
{
String[] phones = XWPrefs.getSMSPhones( this );
m_phoneRecs = new ArrayList<PhoneRec>(phones.length);
for ( String phone : phones ) {
PhoneRec rec = new PhoneRec( phone );
m_phoneRecs.add( rec );
}
}
private void saveAndRebuild()
{
String[] phones = new String[m_phoneRecs.size()];
Iterator<PhoneRec> iter = m_phoneRecs.iterator();
for ( int ii = 0; iter.hasNext(); ++ii ) {
PhoneRec rec = iter.next();
phones[ii] = rec.m_phone;
}
XWPrefs.setSMSPhones( this, phones );
rebuildList( false );
}
private void addChecked( PhoneRec rec )
{
if ( m_nMissing <= countChecks() ) {
Iterator<PhoneRec> iter = m_phoneRecs.iterator();
while ( iter.hasNext() ) {
iter.next().m_checked = false;
}
}
rec.m_checked = true;
m_phoneRecs.add( rec );
}
private void clearSelectedImpl()
{
int count = m_adapter.getCount();
for ( int ii = count - 1; ii >= 0; --ii ) {
if ( m_phoneRecs.get( ii ).m_checked ) {
m_phoneRecs.remove( ii );
}
}
saveAndRebuild();
}
private class PhoneRec {
public String m_phone;
public String m_name;
public boolean m_checked;
public PhoneRec( String name, String phone )
{
this( name, phone, false );
}
public PhoneRec( String phone )
{
this( null, phone, false );
}
public PhoneRec( String name, String phone, boolean checked )
{
m_phone = phone;
m_checked = checked;
if ( null == name ) {
name = Utils.phoneToContact( SMSInviteActivity.this,
phone, false );
if ( null == name ) {
name = getString( R.string.manual_owner_name );
}
}
m_name = name;
}
}
private class SMSPhonesAdapter extends XWListAdapter {
private SMSListItem[] m_items;
public SMSPhonesAdapter()
{
super( m_phoneRecs.size() );
m_items = new SMSListItem[m_phoneRecs.size()];
}
public Object getItem( final int position )
{
// For some reason I can't cache items to be returned.
// Checking/unchecking breaks for some but not all items,
// with some relation to whether they were scrolled into
// view. So build them anew each time (but still cache
// for by-index access.)
SMSListItem item =
(SMSListItem)LocUtils.inflate( SMSInviteActivity.this,
R.layout.smsinviter_item );
item.setChecked( m_phoneRecs.get(position).m_checked );
CompoundButton.OnCheckedChangeListener lstnr =
new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged( CompoundButton bv,
boolean isChecked ) {
m_phoneRecs.get(position).m_checked = isChecked;
tryEnable();
}
};
item.setOnCheckedChangeListener( lstnr );
PhoneRec rec = m_phoneRecs.get( position );
item.setContents( rec.m_name, rec.m_phone );
m_items[position] = item;
return item;
}
public View getView( final int position, View convertView,
ViewGroup parent ) {
return (View)getItem( position );
}
public boolean isChecked( int index )
{
SMSListItem item = m_items[index];
boolean checked = null != item && item.isChecked();
return checked;
}
}
}

View file

@ -0,0 +1,418 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2012 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 android.app.Activity;
import android.app.ListActivity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract;
import android.text.method.DialerKeyListener;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import org.eehouse.android.xw4.DlgDelegate.Action;
public class SMSInviteDelegate extends InviteDelegate {
private static final int GET_CONTACT = 1;
private static final String SAVE_NAME = "SAVE_NAME";
private static final String SAVE_NUMBER = "SAVE_NUMBER";
private ArrayList<PhoneRec> m_phoneRecs;
private SMSPhonesAdapter m_adapter;
private ImageButton m_addButton;
private String m_pendingName;
private String m_pendingNumber;
private boolean m_immobileConfirmed;
private ListActivity m_activity;
public static void launchForResult( Activity activity, int nMissing,
int requestCode )
{
Intent intent = new Intent( activity, SMSInviteActivity.class );
intent.putExtra( INTENT_KEY_NMISSING, nMissing );
activity.startActivityForResult( intent, requestCode );
}
public SMSInviteDelegate( ListActivity activity, Bundle savedInstanceState )
{
super( activity, savedInstanceState );
m_activity = activity;
}
protected void init( Bundle savedInstanceState )
{
super.init( R.layout.smsinviter,
R.id.button_invite, R.id.button_add,
R.id.button_clear, R.id.invite_desc,
R.string.invite_sms_desc_fmt );
getBundledData( savedInstanceState );
m_addButton = (ImageButton)findViewById( R.id.manual_add_button );
m_addButton.setOnClickListener( new View.OnClickListener() {
public void onClick( View view )
{
showDialog( DlgID.GET_NUMBER );
}
} );
getSavedState();
rebuildList( true );
}
protected void onSaveInstanceState( Bundle outState )
{
outState.putString( SAVE_NAME, m_pendingName );
outState.putString( SAVE_NUMBER, m_pendingNumber );
}
private void getBundledData( Bundle bundle )
{
if ( null != bundle ) {
m_pendingName = bundle.getString( SAVE_NAME );
m_pendingNumber = bundle.getString( SAVE_NUMBER );
}
}
protected void onActivityResult( int requestCode, int resultCode,
Intent data )
{
// super.onActivityResult( requestCode, resultCode, data );
if ( Activity.RESULT_CANCELED != resultCode && data != null ) {
switch (requestCode) {
case GET_CONTACT:
addPhoneNumbers( data );
break;
}
}
}
protected Dialog onCreateDialog( int id )
{
Dialog dialog = super.onCreateDialog( id );
if ( null == dialog ) {
DialogInterface.OnClickListener lstnr;
DlgID dlgID = DlgID.values()[id];
switch( dlgID ) {
case GET_NUMBER:
final GameNamer namerView =
(GameNamer)inflate( R.layout.rename_game );
namerView.setLabel( R.string.get_sms_number );
namerView.setKeyListener(DialerKeyListener.getInstance());
lstnr = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int item ) {
String number = namerView.getName();
PhoneRec rec = new PhoneRec( number );
m_pendingNumber = number;
m_pendingName = null;
showConfirmThen( R.string.warn_unlimited,
R.string.button_yes,
Action.POST_WARNING_ACTION );
}
};
dialog = makeAlertBuilder()
.setNegativeButton( R.string.button_cancel, null )
.setPositiveButton( R.string.button_ok, lstnr )
.setView( namerView )
.create();
break;
}
setRemoveOnDismiss( dialog, dlgID );
}
return dialog;
}
protected void scan()
{
Intent intent = new Intent( Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI );
intent.setType( Phone.CONTENT_TYPE );
startActivityForResult( intent, GET_CONTACT );
}
protected void clearSelected()
{
showConfirmThen( R.string.confirm_clear, Action.CLEAR_ACTION );
}
protected String[] listSelected()
{
int count = m_adapter.getCount();
String[] result = new String[countChecks()];
int index = 0;
Iterator<PhoneRec> iter = m_phoneRecs.iterator();
for ( int ii = 0; iter.hasNext(); ++ii ) {
if ( iter.next().m_checked ) {
result[index++] =
((SMSListItem)m_adapter.getItem(ii)).getNumber();
}
}
return result;
}
@Override
protected void tryEnable()
{
int count = countChecks();
m_okButton.setEnabled( count == m_nMissing );
m_clearButton.setEnabled( 0 < count );
}
// DlgDelegate.DlgClickNotify interface
@Override
public void dlgButtonClicked( Action action, int which, Object[] params )
{
switch( which ) {
case AlertDialog.BUTTON_POSITIVE:
switch( action ) {
case CLEAR_ACTION:
clearSelectedImpl();
break;
case USE_IMMOBILE_ACTION:
m_immobileConfirmed = true;
break;
case POST_WARNING_ACTION:
addChecked( new PhoneRec( m_pendingName, m_pendingNumber ) );
saveAndRebuild();
break;
}
break;
case DlgDelegate.DISMISS_BUTTON:
if ( Action.USE_IMMOBILE_ACTION == action && m_immobileConfirmed ) {
showConfirmThen( R.string.warn_unlimited,
R.string.button_yes,
Action.POST_WARNING_ACTION );
}
break;
}
}
private int countChecks()
{
int count = 0;
if ( null != m_phoneRecs ) {
Iterator<PhoneRec> iter = m_phoneRecs.iterator();
while ( iter.hasNext() ) {
if ( iter.next().m_checked ) {
++count;
}
}
}
return count;
}
private void addPhoneNumbers( Intent intent )
{
Uri data = intent.getData();
Cursor cursor = m_activity
.managedQuery( data,
new String[] { Phone.DISPLAY_NAME,
Phone.NUMBER,
Phone.TYPE },
null, null, null );
// Have seen a crash reporting
// "android.database.StaleDataException: Attempted to access a
// cursor after it has been closed." when the query takes a
// long time to return. Be safe.
if ( null != cursor && !cursor.isClosed() ) {
if ( cursor.moveToFirst() ) {
String name =
cursor.getString( cursor.
getColumnIndex( Phone.DISPLAY_NAME));
String number =
cursor.getString( cursor.
getColumnIndex( Phone.NUMBER ) );
int type = cursor.getInt( cursor.
getColumnIndex( Phone.TYPE ) );
m_pendingName = name;
m_pendingNumber = number;
if ( Phone.TYPE_MOBILE == type ) {
showConfirmThen( R.string.warn_unlimited,
R.string.button_yes,
Action.POST_WARNING_ACTION );
} else {
m_immobileConfirmed = false;
String msg = getString( R.string.warn_nomobile_fmt,
number, name );
showConfirmThen( msg, R.string.button_yes,
Action.USE_IMMOBILE_ACTION );
}
}
}
} // addPhoneNumbers
private void rebuildList( boolean checkIfAll )
{
Collections.sort( m_phoneRecs, new Comparator<PhoneRec>() {
public int compare( PhoneRec rec1, PhoneRec rec2 ) {
return rec1.m_name.compareTo(rec2.m_name);
}
});
m_adapter = new SMSPhonesAdapter();
setListAdapter( m_adapter );
if ( checkIfAll && m_phoneRecs.size() <= m_nMissing ) {
Iterator<PhoneRec> iter = m_phoneRecs.iterator();
while ( iter.hasNext() ) {
iter.next().m_checked = true;
}
}
tryEnable();
}
private void getSavedState()
{
String[] phones = XWPrefs.getSMSPhones( m_activity );
m_phoneRecs = new ArrayList<PhoneRec>(phones.length);
for ( String phone : phones ) {
PhoneRec rec = new PhoneRec( phone );
m_phoneRecs.add( rec );
}
}
private void saveAndRebuild()
{
String[] phones = new String[m_phoneRecs.size()];
Iterator<PhoneRec> iter = m_phoneRecs.iterator();
for ( int ii = 0; iter.hasNext(); ++ii ) {
PhoneRec rec = iter.next();
phones[ii] = rec.m_phone;
}
XWPrefs.setSMSPhones( m_activity, phones );
rebuildList( false );
}
private void addChecked( PhoneRec rec )
{
if ( m_nMissing <= countChecks() ) {
Iterator<PhoneRec> iter = m_phoneRecs.iterator();
while ( iter.hasNext() ) {
iter.next().m_checked = false;
}
}
rec.m_checked = true;
m_phoneRecs.add( rec );
}
private void clearSelectedImpl()
{
int count = m_adapter.getCount();
for ( int ii = count - 1; ii >= 0; --ii ) {
if ( m_phoneRecs.get( ii ).m_checked ) {
m_phoneRecs.remove( ii );
}
}
saveAndRebuild();
}
private class PhoneRec {
public String m_phone;
public String m_name;
public boolean m_checked;
public PhoneRec( String name, String phone )
{
this( name, phone, false );
}
public PhoneRec( String phone )
{
this( null, phone, false );
}
public PhoneRec( String name, String phone, boolean checked )
{
m_phone = phone;
m_checked = checked;
if ( null == name ) {
name = Utils.phoneToContact( m_activity, phone, false );
if ( null == name ) {
name = getString( R.string.manual_owner_name );
}
}
m_name = name;
}
}
private class SMSPhonesAdapter extends XWListAdapter {
private SMSListItem[] m_items;
public SMSPhonesAdapter()
{
super( m_phoneRecs.size() );
m_items = new SMSListItem[m_phoneRecs.size()];
}
public Object getItem( final int position )
{
// For some reason I can't cache items to be returned.
// Checking/unchecking breaks for some but not all items,
// with some relation to whether they were scrolled into
// view. So build them anew each time (but still cache
// for by-index access.)
SMSListItem item =
(SMSListItem)inflate( R.layout.smsinviter_item );
item.setChecked( m_phoneRecs.get(position).m_checked );
CompoundButton.OnCheckedChangeListener lstnr =
new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged( CompoundButton bv,
boolean isChecked ) {
m_phoneRecs.get(position).m_checked = isChecked;
tryEnable();
}
};
item.setOnCheckedChangeListener( lstnr );
PhoneRec rec = m_phoneRecs.get( position );
item.setContents( rec.m_name, rec.m_phone );
m_items[position] = item;
return item;
}
public View getView( final int position, View convertView,
ViewGroup parent ) {
return (View)getItem( position );
}
public boolean isChecked( int index )
{
SMSListItem item = m_items[index];
boolean checked = null != item && item.isChecked();
return checked;
}
}
}

View file

@ -46,7 +46,7 @@ import org.eehouse.android.xw4.DlgDelegate.Action;
import org.eehouse.android.xw4.jni.GameSummary;
import org.eehouse.android.xw4.loc.LocUtils;
public class StudyListDelegate extends DelegateBase
public class StudyListDelegate extends ListDelegateBase
implements OnItemSelectedListener, SelectableItem,
View.OnLongClickListener, View.OnClickListener {
@ -256,7 +256,7 @@ public class StudyListDelegate extends DelegateBase
private void makeAdapter()
{
m_adapter = new SLWordsAdapter();
m_activity.setListAdapter( m_adapter );
setListAdapter( m_adapter );
}
private void initOrFinish( Intent startIntent )

View file

@ -1,190 +0,0 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2010 - 2011 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 android.app.ListActivity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import org.eehouse.android.xw4.DlgDelegate.Action;
import junit.framework.Assert;
public class XWListActivity extends ListActivity
implements DlgDelegate.DlgClickNotify, MultiService.MultiEventListener {
private DlgDelegate m_delegate;
@Override
protected void onCreate( Bundle savedInstanceState )
{
DbgUtils.logf( "%s.onCreate(this=%H)", getClass().getName(), this );
super.onCreate( savedInstanceState );
m_delegate = new DlgDelegate( this, this, savedInstanceState );
}
@Override
protected void onStart()
{
DbgUtils.logf( "%s.onStart(this=%H)", getClass().getName(), this );
super.onStart();
}
@Override
protected void onResume()
{
DbgUtils.logf( "%s.onResume(this=%H)", getClass().getName(), this );
XWService.setListener( this );
super.onResume();
}
@Override
protected void onPause()
{
DbgUtils.logf( "%s.onPause(this=%H)", getClass().getName(), this );
XWService.setListener( null );
super.onPause();
}
@Override
protected void onStop()
{
DbgUtils.logf( "%s.onStop(this=%H)", getClass().getName(), this );
super.onStop();
}
@Override
protected void onDestroy()
{
DbgUtils.logf( "%s.onDestroy(this=%H); isFinishing=%b",
getClass().getName(), this, isFinishing() );
super.onDestroy();
}
@Override
protected void onSaveInstanceState( Bundle outState )
{
super.onSaveInstanceState( outState );
m_delegate.onSaveInstanceState( outState );
}
@Override
protected Dialog onCreateDialog( final int id )
{
DbgUtils.logf( "%s.onCreateDialog() called", getClass().getName() );
Dialog dialog = m_delegate.createDialog( id );
if ( null == dialog ) {
dialog = super.onCreateDialog( id );
}
return dialog;
}
protected void showNotAgainDlgThen( int msgID, int prefsKey,
Action action )
{
m_delegate.showNotAgainDlgThen( msgID, prefsKey, action );
}
protected void showNotAgainDlg( int msgID, int prefsKey )
{
m_delegate.showNotAgainDlgThen( msgID, prefsKey );
}
protected void showOKOnlyDialogThen( String msg, Action action )
{
m_delegate.showOKOnlyDialog( msg, action );
}
protected void showOKOnlyDialog( String msg )
{
m_delegate.showOKOnlyDialog( msg );
}
protected void showOKOnlyDialog( int msgID )
{
m_delegate.showOKOnlyDialog( msgID );
}
protected void showConfirmThen( String msg, Action action )
{
m_delegate.showConfirmThen( msg, action );
}
protected void showConfirmThen( int msg, Action action )
{
showConfirmThen( getString(msg), action );
}
protected void showConfirmThen( String msg, int posButton, Action action )
{
m_delegate.showConfirmThen( msg, posButton, action );
}
protected void showConfirmThen( int msg, int posButton, Action action )
{
m_delegate.showConfirmThen( getString(msg), posButton, action );
}
protected void doSyncMenuitem()
{
m_delegate.doSyncMenuitem();
}
protected void startProgress( int id )
{
m_delegate.startProgress( id );
}
protected void stopProgress()
{
m_delegate.stopProgress();
}
protected boolean post( Runnable runnable )
{
return m_delegate.post( runnable );
}
// DlgDelegate.DlgClickNotify interface
public void dlgButtonClicked( Action action, int which, Object[] params )
{
Assert.fail();
}
protected void launchLookup( String[] words, int lang, boolean noStudy )
{
m_delegate.launchLookup( words, lang, noStudy );
}
protected void launchLookup( String[] words, int lang )
{
m_delegate.launchLookup( words, lang, false );
}
// MultiService.MultiEventListener interface
public void eventOccurred( MultiService.MultiEvent event,
final Object ... args )
{
m_delegate.eventOccurred( event, args );
}
}