turn on face-up tile picking for Android (though there's no prefs UI

to enable it for a game yet).  In common code, break pick tile utils
method in two, one for blank and the other for tray tiles.  In java,
implement dialog for picking the tiles.  Works, though is a bit clumsy
to have the dialog come and go after every pick.  Better would be a
dialog that stays up and accumulates picks -- but it'd have to know to
reduce the set of tile choices as letters are chosen.  This'll do for
now.
This commit is contained in:
Andy2 2011-10-28 22:15:56 -07:00
parent f6ff3e85c6
commit 8d228ae190
13 changed files with 157 additions and 58 deletions

View file

@ -24,6 +24,7 @@ local_DEFINES += \
-DDISABLE_EMPTYTRAY_UNDO \
-DDISABLE_TILE_SEL \
-DXWFEATURE_BOARDWORDS \
-DFEATURE_TRAY_EDIT \
-DNODE_CAN_4 \
-DRELAY_ROOM_DEFAULT=\"\"\
-D__LITTLE_ENDIAN \

View file

@ -145,17 +145,13 @@ and_util_confirmTrade( XW_UtilCtxt* uc, const XP_UCHAR** tiles, XP_U16 nTiles )
}
static XP_S16
and_util_userPickTile( XW_UtilCtxt* uc, const PickInfo* pi,
XP_U16 playerNum, const XP_UCHAR** texts, XP_U16 nTiles )
and_util_userPickTileBlank( XW_UtilCtxt* uc, XP_U16 playerNum,
const XP_UCHAR** tileFaces, XP_U16 nTiles )
{
XP_S16 result = -1;
UTIL_CBK_HEADER("userPickTile", "(I[Ljava/lang/String;)I" );
UTIL_CBK_HEADER("userPickTileBlank", "(I[Ljava/lang/String;)I" );
#ifdef FEATURE_TRAY_EDIT
++error; /* need to pass pi if this is on */
#endif
jobject jtexts = makeStringArray( env, nTiles, texts );
jobject jtexts = makeStringArray( env, nTiles, tileFaces );
result = (*env)->CallIntMethod( env, util->jutil, mid,
playerNum, jtexts );
@ -163,8 +159,27 @@ and_util_userPickTile( XW_UtilCtxt* uc, const PickInfo* pi,
(*env)->DeleteLocalRef( env, jtexts );
UTIL_CBK_TAIL();
return result;
} /* and_util_userPickTile */
}
static XP_S16
and_util_userPickTileTray( XW_UtilCtxt* uc, const PickInfo* pi,
XP_U16 playerNum, const XP_UCHAR** tileFaces,
XP_U16 nTiles )
{
XP_S16 result = -1;
UTIL_CBK_HEADER("userPickTileTray",
"(I[Ljava/lang/String;[Ljava/lang/String;I)I" );
jobject jtexts = makeStringArray( env, nTiles, tileFaces );
jobject jcurtiles = makeStringArray( env, pi->nCurTiles, pi->curTiles );
result = (*env)->CallIntMethod( env, util->jutil, mid,
playerNum, jtexts, jcurtiles,
pi->thisPick );
(*env)->DeleteLocalRef( env, jtexts );
(*env)->DeleteLocalRef( env, jcurtiles );
UTIL_CBK_TAIL();
return result;
} /* and_util_userPickTile */
static XP_Bool
and_util_askPassword( XW_UtilCtxt* uc, const XP_UCHAR* name,
@ -511,7 +526,8 @@ makeUtil( MPFORMAL JNIEnv** envp, jobject jutil, CurGameInfo* gi,
SET_PROC(userError);
SET_PROC(userQuery);
SET_PROC(confirmTrade);
SET_PROC(userPickTile);
SET_PROC(userPickTileBlank);
SET_PROC(userPickTileTray);
SET_PROC(askPassword);
SET_PROC(trayHiddenChange);
SET_PROC(yOffsetChange);

View file

@ -1783,5 +1783,9 @@
<string name="button_move">Move</string>
<string name="tilepick_undo">Undo last</string>
<string name="tilepick_all">Pick for me</string>
<string name="cur_tilesf">Tile picker\n(so far: %s)</string>
</resources>

View file

@ -65,7 +65,7 @@ public class BoardActivity extends XWActivity
private static final int DLG_BADWORDS = DLG_OKONLY + 1;
private static final int QUERY_REQUEST_BLK = DLG_OKONLY + 2;
private static final int QUERY_INFORM_BLK = DLG_OKONLY + 3;
private static final int PICK_TILE_REQUEST_BLK = DLG_OKONLY + 4;
private static final int PICK_TILE_REQUESTBLANK_BLK = DLG_OKONLY + 4;
private static final int ASK_PASSWORD_BLK = DLG_OKONLY + 5;
private static final int DLG_RETRY = DLG_OKONLY + 6;
private static final int QUERY_ENDGAME = DLG_OKONLY + 7;
@ -73,6 +73,7 @@ public class BoardActivity extends XWActivity
private static final int DLG_INVITE = DLG_OKONLY + 9;
private static final int DLG_SCORES_BLK = DLG_OKONLY + 10;
private static final int DLG_LOOKUP = DLG_OKONLY + 11;
private static final int PICK_TILE_REQUESTTRAY_BLK = DLG_OKONLY + 12;
private static final int CHAT_REQUEST = 1;
private static final int SCREEN_ON_TIME = 10 * 60 * 1000; // 10 mins
@ -122,6 +123,8 @@ public class BoardActivity extends XWActivity
private int m_dlgTitle;
private String m_dlgTitleStr;
private String[] m_texts;
private String m_curTiles;
private boolean m_canUndoTiles;
private boolean m_firingPrefs;
private JNIUtils m_jniu;
private boolean m_volKeysZoom;
@ -164,7 +167,7 @@ public class BoardActivity extends XWActivity
}
@Override
protected Dialog onCreateDialog( int id )
protected Dialog onCreateDialog( final int id )
{
Dialog dialog = super.onCreateDialog( id );
if ( null == dialog ) {
@ -264,9 +267,9 @@ public class BoardActivity extends XWActivity
dialog.setOnDismissListener( makeODLforBlocking( id ) );
break;
case PICK_TILE_REQUEST_BLK:
ab = new AlertDialog.Builder( this )
.setTitle( R.string.title_tile_picker );
case PICK_TILE_REQUESTBLANK_BLK:
case PICK_TILE_REQUESTTRAY_BLK:
ab = new AlertDialog.Builder( this );
lstnr = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog,
int item ) {
@ -275,6 +278,34 @@ public class BoardActivity extends XWActivity
};
ab.setItems( m_texts, lstnr );
if ( PICK_TILE_REQUESTBLANK_BLK == id ) {
ab.setTitle( R.string.title_tile_picker );
} else {
ab.setTitle( Utils.format( this, R.string.cur_tilesf,
m_curTiles ) );
if ( m_canUndoTiles ) {
DialogInterface.OnClickListener undoClicked =
new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog,
int whichButton ) {
m_resultCode = UtilCtxt.PICKER_BACKUP;
removeDialog( id );
}
};
ab.setPositiveButton( R.string.tilepick_undo,
undoClicked );
}
DialogInterface.OnClickListener doAllClicked =
new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog,
int whichButton ) {
m_resultCode = UtilCtxt.PICKER_PICKALL;
removeDialog( id );
}
};
ab.setNegativeButton( R.string.tilepick_all, doAllClicked );
}
dialog = ab.create();
dialog.setOnDismissListener( makeODLforBlocking( id ) );
break;
@ -1053,10 +1084,22 @@ public class BoardActivity extends XWActivity
// This is supposed to be called from the jni thread
@Override
public int userPickTile( int playerNum, String[] texts )
public int userPickTileBlank( int playerNum, String[] texts)
{
m_texts = texts;
waitBlockingDialog( PICK_TILE_REQUEST_BLK, 0 );
waitBlockingDialog( PICK_TILE_REQUESTBLANK_BLK, 0 );
return m_resultCode;
}
@Override
public int userPickTileTray( int playerNum, String[] texts,
String[] curTiles, int nPicked )
{
m_texts = texts;
m_curTiles = TextUtils.join( ", ", curTiles );
m_canUndoTiles = 0 < nPicked;
waitBlockingDialog( PICK_TILE_REQUESTTRAY_BLK,
UtilCtxt.PICKER_PICKALL );
return m_resultCode;
}

View file

@ -27,8 +27,13 @@ public interface UtilCtxt {
static final int BONUS_TRIPLE_LETTER = 3;
static final int BONUS_TRIPLE_WORD = 4;
int userPickTile( /* PickInfo* pi, add once tile-picking is enabled */
int playerNum, String[] texts );
// must match defns in util.h
public static final int PICKER_PICKALL = -1;
public static final int PICKER_BACKUP = -2;
int userPickTileBlank( int playerNum, String[] texts );
int userPickTileTray( int playerNum, String[] tiles,
String[] curTiles, int nPicked );
String askPassword( String name );
void turnChanged();

View file

@ -40,9 +40,16 @@ public class UtilCtxtImpl implements UtilCtxt {
subclassOverride( "requestTime" );
}
public int userPickTile( int playerNum, String[] texts )
public int userPickTileBlank( int playerNum, String[] texts )
{
subclassOverride( "userPickTile" );
subclassOverride( "userPickTileBlank" );
return 0;
}
public int userPickTileTray( int playerNum, String[] texts,
String[] curTiles, int nPicked )
{
subclassOverride( "userPickTileTray" );
return 0;
}

View file

@ -1095,17 +1095,11 @@ askBlankTile( ModelCtxt* model, XP_U16 turn )
XP_S16 chosen;
const XP_UCHAR* tfaces[MAX_UNIQUE_TILES];
Tile tiles[MAX_UNIQUE_TILES];
PickInfo pi;
pi.why = PICK_FOR_BLANK;
pi.nTotal = 1;
pi.thisPick = 1;
model_packTilesUtil( model, NULL, XP_FALSE,
&nUsed, tfaces, tiles );
chosen = util_userPickTile( model->vol.util, &pi,
turn, tfaces, nUsed );
chosen = util_userPickTileBlank( model->vol.util, turn, tfaces, nUsed );
if ( chosen < 0 ) {
chosen = 0;

View file

@ -1547,7 +1547,6 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
oneTile.nTiles = 1;
pi.why = PICK_FOR_CHEAT;
pi.nTotal = nToFetch;
pi.thisPick = 0;
pi.curTiles = curTray;
@ -1565,8 +1564,8 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
model_packTilesUtil( server->vol.model, pool,
XP_TRUE, &nUsed, texts, tiles );
chosen = util_userPickTile( server->vol.util, &pi, playerNum,
texts, nUsed );
chosen = util_userPickTileTray( server->vol.util, &pi, playerNum,
texts, nUsed );
if ( chosen == PICKER_PICKALL ) {
ask = XP_FALSE;

View file

@ -70,11 +70,6 @@ typedef enum {
QUERY_LAST_COMMON
} UtilQueryID;
typedef enum {
PICK_FOR_BLANK
, PICK_FOR_CHEAT
} PICK_WHY;
#define PICKER_PICKALL -1
#define PICKER_BACKUP -2
@ -83,7 +78,6 @@ typedef struct PickInfo {
XP_U16 nCurTiles;
XP_U16 nTotal; /* count to fetch for turn, <= MAX_TRAY_TILES */
XP_U16 thisPick; /* <= nTotal */
PICK_WHY why;
} PickInfo;
typedef struct BadWordInfo {
@ -115,9 +109,12 @@ typedef struct UtilVtable {
XP_Bool (*m_util_confirmTrade)( XW_UtilCtxt* uc, const XP_UCHAR** tiles,
XP_U16 nTiles );
/* return of < 0 means computer should pick */
XP_S16 (*m_util_userPickTile)( XW_UtilCtxt* uc, const PickInfo* pi,
XP_U16 playerNum,
const XP_UCHAR** texts, XP_U16 nTiles );
XP_S16 (*m_util_userPickTileBlank)( XW_UtilCtxt* uc, XP_U16 playerNum,
const XP_UCHAR** tileFaces,
XP_U16 nTiles );
XP_S16 (*m_util_userPickTileTray)( XW_UtilCtxt* uc, const PickInfo* pi,
XP_U16 playerNum,
const XP_UCHAR** texts, XP_U16 nTiles );
XP_Bool (*m_util_askPassword)( XW_UtilCtxt* uc, const XP_UCHAR* name,
XP_UCHAR* buf, XP_U16* len );
@ -216,8 +213,10 @@ struct XW_UtilCtxt {
#define util_confirmTrade( uc, tx, nt ) \
(uc)->vtable->m_util_confirmTrade((uc),(tx),(nt))
#define util_userPickTile( uc, w, n, tx, nt ) \
(uc)->vtable->m_util_userPickTile( (uc), (w), (n), (tx), (nt) )
#define util_userPickTileBlank( uc, n, tx, nt ) \
(uc)->vtable->m_util_userPickTileBlank( (uc), (n), (tx), (nt) )
#define util_userPickTileTray( uc, w, n, tx, nt ) \
(uc)->vtable->m_util_userPickTileTray( (uc), (w), (n), (tx), (nt) )
#define util_askPassword( uc, n, b, lp ) \
(uc)->vtable->m_util_askPassword( (uc), (n), (b), (lp) )

View file

@ -228,9 +228,26 @@ cursesUserError( CursesAppGlobals* globals, const char* format, ... )
} /* cursesUserError */
static XP_S16
curses_util_userPickTile( XW_UtilCtxt* uc, const PickInfo* XP_UNUSED(pi),
XP_U16 playerNum, const XP_UCHAR** texts,
XP_U16 nTiles )
curses_util_userPickTileBlank( XW_UtilCtxt* uc, XP_U16 playerNum,
const XP_UCHAR** texts, XP_U16 nTiles )
{
CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure;
char query[128];
XP_S16 index;
char* playerName = globals->cGlobals.params->gi.players[playerNum].name;
snprintf( query, sizeof(query),
"Pick tile for %s! (Tab or type letter to select "
"then hit <cr>.)", playerName );
index = curses_askLetter( globals, query, texts, nTiles );
return index;
} /* util_userPickTile */
static XP_S16
curses_util_userPickTileTray( XW_UtilCtxt* uc, const PickInfo* XP_UNUSED(pi),
XP_U16 playerNum, const XP_UCHAR** texts,
XP_U16 nTiles )
{
CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure;
char query[128];
@ -1478,7 +1495,8 @@ setupCursesUtilCallbacks( CursesAppGlobals* globals, XW_UtilCtxt* util )
#endif
util->vtable->m_util_userQuery = curses_util_userQuery;
util->vtable->m_util_confirmTrade = curses_util_confirmTrade;
util->vtable->m_util_userPickTile = curses_util_userPickTile;
util->vtable->m_util_userPickTileBlank = curses_util_userPickTileBlank;
util->vtable->m_util_userPickTileTray = curses_util_userPickTileTray;
util->vtable->m_util_trayHiddenChange = curses_util_trayHiddenChange;
util->vtable->m_util_informMove = curses_util_informMove;
util->vtable->m_util_notifyGameOver = curses_util_notifyGameOver;

View file

@ -42,7 +42,7 @@ abort_button_event( GtkWidget* XP_UNUSED(widget), gpointer XP_UNUSED(closure) )
#define BUTTONS_PER_ROW 13
XP_S16
gtkletterask( const PickInfo* pi, const XP_UCHAR* name,
gtkletterask( const PickInfo* pi, XP_Bool forTray, const XP_UCHAR* name,
XP_U16 nTiles, const XP_UCHAR** texts )
{
GtkWidget* dialog;
@ -103,19 +103,18 @@ gtkletterask( const PickInfo* pi, const XP_UCHAR* name,
dialog = gtk_dialog_new();
gtk_window_set_modal( GTK_WINDOW( dialog ), TRUE );
XP_Bool forBlank = PICK_FOR_BLANK == pi->why;
if ( forBlank ) {
txt = "Choose a letter for your blank.";
} else {
if ( forTray ) {
char* fmt = "Choose a tile for %s.";
XP_SNPRINTF( buf, sizeof(buf), fmt, name );
txt = buf;
} else {
txt = "Choose a letter for your blank.";
}
label = gtk_label_new( txt );
gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
label);
if ( !forBlank ) {
if ( forTray ) {
char curTilesBuf[64];
int len = snprintf( curTilesBuf, sizeof(curTilesBuf), "%s",
"Tiles so far: " );

View file

@ -26,7 +26,8 @@
#include "gtkmain.h"
XP_S16 gtkletterask( const PickInfo* pi, const XP_UCHAR* name,
XP_S16 gtkletterask( const PickInfo* pi, XP_Bool forTray,
const XP_UCHAR* name,
XP_U16 nTiles, const XP_UCHAR** texts );

View file

@ -1300,15 +1300,27 @@ gtk_util_getVTManager(XW_UtilCtxt* uc)
} /* linux_util_getVTManager */
static XP_S16
gtk_util_userPickTile( XW_UtilCtxt* uc, const PickInfo* pi,
XP_U16 playerNum, const XP_UCHAR** texts,
XP_U16 nTiles )
gtk_util_userPickTileBlank( XW_UtilCtxt* uc, XP_U16 playerNum,
const XP_UCHAR** texts, XP_U16 nTiles )
{
XP_S16 chosen;
GtkAppGlobals* globals = (GtkAppGlobals*)uc->closure;
XP_UCHAR* name = globals->cGlobals.params->gi.players[playerNum].name;
chosen = gtkletterask( pi, name, nTiles, texts );
chosen = gtkletterask( NULL, XP_FALSE, name, nTiles, texts );
return chosen;
}
static XP_S16
gtk_util_userPickTileTray( XW_UtilCtxt* uc, const PickInfo* pi,
XP_U16 playerNum, const XP_UCHAR** texts,
XP_U16 nTiles )
{
XP_S16 chosen;
GtkAppGlobals* globals = (GtkAppGlobals*)uc->closure;
XP_UCHAR* name = globals->cGlobals.params->gi.players[playerNum].name;
chosen = gtkletterask( pi, XP_TRUE, name, nTiles, texts );
return chosen;
} /* gtk_util_userPickTile */
@ -1930,7 +1942,8 @@ setupGtkUtilCallbacks( GtkAppGlobals* globals, XW_UtilCtxt* util )
util->vtable->m_util_userQuery = gtk_util_userQuery;
util->vtable->m_util_confirmTrade = gtk_util_confirmTrade;
util->vtable->m_util_getVTManager = gtk_util_getVTManager;
util->vtable->m_util_userPickTile = gtk_util_userPickTile;
util->vtable->m_util_userPickTileBlank = gtk_util_userPickTileBlank;
util->vtable->m_util_userPickTileTray = gtk_util_userPickTileTray;
util->vtable->m_util_askPassword = gtk_util_askPassword;
util->vtable->m_util_trayHiddenChange = gtk_util_trayHiddenChange;
util->vtable->m_util_yOffsetChange = gtk_util_yOffsetChange;