diff --git a/xwords4/android/XWords4/jni/xwjni.c b/xwords4/android/XWords4/jni/xwjni.c index 4c60d262b..cb4ac5651 100644 --- a/xwords4/android/XWords4/jni/xwjni.c +++ b/xwords4/android/XWords4/jni/xwjni.c @@ -684,6 +684,17 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1beginTrade return result; } +JNIEXPORT jboolean JNICALL +Java_org_eehouse_android_xw4_jni_XwJNI_board_1endTrade +( JNIEnv* env, jclass C, jint gamePtr ) +{ + jboolean result; + XWJNI_START(); + result = board_endTrade( state->game.board ); + XWJNI_END(); + return result; +} + JNIEXPORT jboolean JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_board_1toggle_1showValues ( JNIEnv* env, jclass C, jint gamePtr ) @@ -1090,61 +1101,6 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1focusChanged } #endif -JNIEXPORT jint JNICALL -Java_org_eehouse_android_xw4_jni_XwJNI_board_1visTileCount -( JNIEnv* env, jclass C, jint gamePtr ) -{ - jint result; - XWJNI_START(); - result = board_visTileCount( state->game.board ); - XWJNI_END(); - return result; -} - -JNIEXPORT jboolean JNICALL -Java_org_eehouse_android_xw4_jni_XwJNI_board_1canHint -( JNIEnv* env, jclass C, jint gamePtr ) -{ - jboolean result; - XWJNI_START(); - result = board_canHint( state->game.board ); - XWJNI_END(); - return result; -} - -JNIEXPORT jboolean JNICALL -Java_org_eehouse_android_xw4_jni_XwJNI_board_1canShuffle -( JNIEnv* env, jclass C, jint gamePtr ) -{ - jboolean result; - XWJNI_START(); - result = board_canShuffle( state->game.board ); - XWJNI_END(); - return result; -} - -JNIEXPORT jboolean JNICALL -Java_org_eehouse_android_xw4_jni_XwJNI_board_1canTogglePending -( JNIEnv* env, jclass C, jint gamePtr ) -{ - jboolean result; - XWJNI_START(); - result = board_canTogglePending( state->game.board ); - XWJNI_END(); - return result; -} - -JNIEXPORT jboolean JNICALL -Java_org_eehouse_android_xw4_jni_XwJNI_comms_1canChat -( JNIEnv* env, jclass C, jint gamePtr ) -{ - jboolean result; - XWJNI_START(); - result = NULL != state->game.comms && comms_canChat( state->game.comms ); - XWJNI_END(); - return result; -} - #ifdef KEYBOARD_NAV JNIEXPORT jboolean JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_board_1handleKey @@ -1177,6 +1133,24 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1getGi XWJNI_END(); } +JNIEXPORT void JNICALL +Java_org_eehouse_android_xw4_jni_XwJNI_game_1getState +( JNIEnv* env, jclass C, jint gamePtr, jobject jgsi ) +{ + XWJNI_START(); + GameStateInfo info; + game_getState( &state->game, &info ); + + setInt( env, jgsi, "visTileCount", info.visTileCount ); + setBool( env, jgsi, "canHint", info.canHint ); + setBool( env, jgsi, "canRedo", info.canRedo); + setBool( env, jgsi, "inTrade", info.inTrade ); + setBool( env, jgsi, "gameIsConnected", info.gameIsConnected ); + setBool( env, jgsi, "canShuffle", info.canShuffle ); + + XWJNI_END(); +} + JNIEXPORT jboolean JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_game_1hasComms ( JNIEnv* env, jclass C, jint gamePtr ) @@ -1240,4 +1214,3 @@ Java_org_eehouse_android_xw4_jni_XwJNI_server_1sendChat (*env)->ReleaseStringUTFChars( env, jmsg, msg ); XWJNI_END(); } - diff --git a/xwords4/android/XWords4/res/menu/board_menu.xml b/xwords4/android/XWords4/res/menu/board_menu.xml index 0aaaabcfd..411a7d7a5 100644 --- a/xwords4/android/XWords4/res/menu/board_menu.xml +++ b/xwords4/android/XWords4/res/menu/board_menu.xml @@ -1,20 +1,27 @@ - - - - + - + + + + + + + - - - - Shuffle Flip Exchange tiles + Exchange done + Cancel exchange Hide rack Undo Undo current diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java index 6cc141453..7192cf5a5 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -97,6 +97,7 @@ public class BoardActivity extends XWActivity private Thread m_blockingThread; private JNIThread m_jniThread; + private JNIThread.GameStateInfo m_gsi; private ProgressDialog m_progress; private boolean m_isVisible; @@ -386,7 +387,9 @@ public class BoardActivity extends XWActivity return super.onKeyUp( keyCode, event ); } - public boolean onCreateOptionsMenu(Menu menu) { + @Override + public boolean onCreateOptionsMenu( Menu menu ) + { MenuInflater inflater = getMenuInflater(); inflater.inflate( R.menu.board_menu, menu ); @@ -398,6 +401,20 @@ public class BoardActivity extends XWActivity return true; } + @Override + public boolean onPrepareOptionsMenu( Menu menu ) + { + super.onPrepareOptionsMenu( menu ); + + if ( null != m_gsi ) { + boolean inTrade = m_gsi.inTrade; + menu.setGroupVisible( R.id.group_intrade, inTrade ) ; + menu.setGroupVisible( R.id.group_done, !inTrade ); + } + + return true; + } + public boolean onOptionsItemSelected( MenuItem item ) { boolean handled = true; @@ -424,6 +441,13 @@ public class BoardActivity extends XWActivity case R.id.board_menu_trade: cmd = JNIThread.JNICmd.CMD_TRADE; break; + case R.id.board_menu_trade_commit: + cmd = JNIThread.JNICmd.CMD_COMMIT; + break; + case R.id.board_menu_trade_cancel: + cmd = JNIThread.JNICmd.CMD_CANCELTRADE; + break; + case R.id.board_menu_tray: cmd = JNIThread.JNICmd.CMD_TOGGLE_TRAY; break; @@ -1105,7 +1129,8 @@ public class BoardActivity extends XWActivity showDialog( QUERY_ENDGAME ); break; case JNIThread.TOOLBAR_STATES: - m_toolbar.update( msg.arg1, msg.arg2 ); + m_gsi = m_jniThread.getGameStateInfo(); + updateToolbar(); } } } ); @@ -1340,4 +1365,14 @@ public class BoardActivity extends XWActivity } } + private void updateToolbar() + { + m_toolbar.update( Toolbar.BUTTON_FLIP, m_gsi.visTileCount > 1 ); + m_toolbar.update( Toolbar.BUTTON_JUGGLE, m_gsi.canShuffle ); + m_toolbar.update( Toolbar.BUTTON_UNDO, m_gsi.canRedo ); + m_toolbar.update( Toolbar.BUTTON_HINT_PREV, m_gsi.canHint ); + m_toolbar.update( Toolbar.BUTTON_HINT_NEXT, m_gsi.canHint ); + m_toolbar.update( Toolbar.BUTTON_CHAT, m_gsi.gameIsConnected ); + } + } // class BoardActivity diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/Toolbar.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/Toolbar.java index e7fcee11f..a3c82d0ec 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/Toolbar.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/Toolbar.java @@ -134,11 +134,10 @@ public class Toolbar { } } - public void update( int index, int enable ) + public void update( int index, boolean enable ) { - boolean show = enable!=0; TBButtonInfo info = s_buttonInfo[index]; - int vis = enable != 0 ? View.VISIBLE : View.GONE; + int vis = enable ? View.VISIBLE : View.GONE; ImageButton button; for ( int id : info.m_ids ) { diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java index 9faae2fe6..f641a3c4c 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java @@ -62,6 +62,7 @@ public class JNIThread extends Thread { CMD_FLIP, CMD_TOGGLE_TRAY, CMD_TRADE, + CMD_CANCELTRADE, CMD_UNDO_CUR, CMD_UNDO_LAST, CMD_HINT, @@ -87,6 +88,25 @@ public class JNIThread extends Thread { public static final int QUERY_ENDGAME = 4; public static final int TOOLBAR_STATES = 5; + public class GameStateInfo implements Cloneable { + public int visTileCount; + public boolean canHint; + public boolean canRedo; + public boolean inTrade; + public boolean gameIsConnected; + public boolean canShuffle; + public GameStateInfo clone() { + GameStateInfo obj = null; + try { + obj = (GameStateInfo)super.clone(); + } catch ( CloneNotSupportedException cnse ) { + } + return obj; + } + } + + private GameStateInfo m_gsi = new GameStateInfo(); + private boolean m_stopped = false; private int m_jniGamePtr; private GameUtils.GameLock m_lock; @@ -158,6 +178,13 @@ public class JNIThread extends Thread { } } + public GameStateInfo getGameStateInfo() + { + synchronized( m_gsi ) { + return m_gsi.clone(); + } + } + private boolean toggleTray() { boolean draw; int state = XwJNI.board_getTrayVisState( m_jniGamePtr ); @@ -218,28 +245,10 @@ public class JNIThread extends Thread { private void checkButtons() { - int visTileCount = XwJNI.board_visTileCount( m_jniGamePtr ); - int canFlip = visTileCount > 1 ? 1 : 0; - Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_FLIP, - canFlip ).sendToTarget(); - - int canShuffle = XwJNI.board_canShuffle( m_jniGamePtr ) ? 1 : 0; - Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_JUGGLE, - canShuffle ).sendToTarget(); - - int canRedo = XwJNI.board_canTogglePending( m_jniGamePtr ) ? 1 : 0; - Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_UNDO, - canRedo ).sendToTarget(); - - int canHint = XwJNI.board_canHint( m_jniGamePtr ) ? 1 : 0; - Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_HINT_PREV, - canHint ).sendToTarget(); - Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_HINT_NEXT, - canHint ).sendToTarget(); - - int canMsg = XwJNI.comms_canChat( m_jniGamePtr ) ? 1 : 0; - Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_CHAT, - canMsg ).sendToTarget(); + synchronized( m_gsi ) { + XwJNI.game_getState( m_jniGamePtr, m_gsi ); + } + Message.obtain( m_handler, TOOLBAR_STATES ).sendToTarget(); } public void run() @@ -371,6 +380,9 @@ public class JNIThread extends Thread { case CMD_TRADE: draw = XwJNI.board_beginTrade( m_jniGamePtr ); break; + case CMD_CANCELTRADE: + draw = XwJNI.board_endTrade( m_jniGamePtr ); + break; case CMD_UNDO_CUR: draw = XwJNI.board_replaceTiles( m_jniGamePtr ) || XwJNI.board_redoReplacedTiles( m_jniGamePtr ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java index 4558e3b73..461375566 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java @@ -111,6 +111,8 @@ public class XwJNI { public static native byte[] game_saveToStream( int gamePtr, CurGameInfo gi ); public static native void game_getGi( int gamePtr, CurGameInfo gi ); + public static native void game_getState( int gamePtr, + JNIThread.GameStateInfo gsi ); public static native boolean game_hasComms( int gamePtr ); public static native void game_dispose( int gamePtr ); @@ -156,14 +158,10 @@ public class XwJNI { boolean goBackwards, boolean[] workRemains ); public static native boolean board_beginTrade( int gamePtr ); + public static native boolean board_endTrade( int gamePtr ); public static native String board_formatRemainingTiles( int gamePtr ); - public static native int board_visTileCount( int gamePtr ); - public static native boolean board_canHint( int gamePtr ); - public static native boolean board_canShuffle( int gamePtr ); - public static native boolean board_canTogglePending( int gamePtr ); - public enum XP_Key { XP_KEY_NONE, XP_CURSOR_KEY_DOWN, @@ -215,7 +213,6 @@ public class XwJNI { public static native void comms_setAddr( int gamePtr, CommsAddrRec addr ); public static native void comms_resendAll( int gamePtr ); public static native void comms_transportFailed( int gamePtr ); - public static native boolean comms_canChat( int gamePtr ); public static native boolean comms_isConnected( int gamePtr ); // Dicts diff --git a/xwords4/common/board.c b/xwords4/common/board.c index 2610989a3..949f987b1 100644 --- a/xwords4/common/board.c +++ b/xwords4/common/board.c @@ -750,17 +750,14 @@ board_commitTurn( BoardCtxt* board ) result = XP_TRUE; /* there's at least the window to clean up after */ - invalSelTradeWindow( board ); - pti->tradeInProgress = XP_FALSE; - if ( NO_TILES == pti->traySelBits ) { util_userError( board->util, ERR_NO_EMPTY_TRADE ); } else if ( util_userQuery( board->util, QUERY_COMMIT_TRADE, (XWStreamCtxt*)NULL ) ) { result = server_commitTrade( board->server, pti->traySelBits ); - pti->traySelBits = NO_TILES; } + (void)board_endTrade( board ); } else { XP_Bool warn, legal; WordNotifierInfo info; @@ -1570,6 +1567,13 @@ board_flip( BoardCtxt* board ) return board->needsDrawing; } /* board_flip */ +XP_Bool +board_inTrade( const BoardCtxt* board ) +{ + const PerTurnInfo* pti = &board->pti[board->selPlayer]; + return pti->tradeInProgress; +} + XP_Bool board_get_showValues( const BoardCtxt* board ) { @@ -2061,6 +2065,20 @@ board_beginTrade( BoardCtxt* board ) return result; } /* board_beginTrade */ +XP_Bool +board_endTrade( BoardCtxt* board ) +{ + XP_Bool result = board_inTrade( board ); + if ( result ) { + PerTurnInfo* pti = board->selInfo; + invalSelTradeWindow( board ); + pti->tradeInProgress = XP_FALSE; + pti->traySelBits = NO_TILES; + } + return result; +} + + #if defined POINTER_SUPPORT || defined KEYBOARD_NAV static XP_Bool ptOnTradeWindow( BoardCtxt* board, XP_U16 x, XP_U16 y ) diff --git a/xwords4/common/board.h b/xwords4/common/board.h index 084d72dc6..92750cf33 100644 --- a/xwords4/common/board.h +++ b/xwords4/common/board.h @@ -100,6 +100,7 @@ XP_Bool board_draw( BoardCtxt* board ); XP_Bool board_get_flipped( const BoardCtxt* board ); XP_Bool board_flip( BoardCtxt* board ); +XP_Bool board_inTrade( const BoardCtxt* board ); XP_Bool board_get_showValues( const BoardCtxt* board ); XP_Bool board_toggle_showValues( BoardCtxt* board ); XP_Bool board_replaceTiles( BoardCtxt* board ); @@ -158,6 +159,7 @@ XW_TrayVisState board_getTrayVisState( const BoardCtxt* board ); void board_invalTrayTiles( BoardCtxt* board, TileBit what ); XP_Bool board_juggleTray( BoardCtxt* board ); XP_Bool board_beginTrade( BoardCtxt* board ); +XP_Bool board_endTrade( BoardCtxt* board ); #if defined FOR_GREMLINS XP_Bool board_moveDivider( BoardCtxt* board, XP_Bool right ); diff --git a/xwords4/common/game.c b/xwords4/common/game.c index 0ee1ed425..c2c7af1a1 100644 --- a/xwords4/common/game.c +++ b/xwords4/common/game.c @@ -261,6 +261,17 @@ game_saveToStream( const XWGame* game, const CurGameInfo* gi, } } /* game_saveToStream */ +void +game_getState( const XWGame* game, GameStateInfo* gsi ) +{ + gsi->visTileCount = board_visTileCount( game->board ); + gsi->canHint = board_canHint( game->board ); + gsi->canRedo = board_canTogglePending( game->board ); + gsi->inTrade = board_inTrade( game->board ); + gsi->gameIsConnected = !!game->comms && comms_canChat( game->comms ); + gsi->canShuffle = board_canShuffle( game->board ); +} + void game_dispose( XWGame* game ) { diff --git a/xwords4/common/game.h b/xwords4/common/game.h index b7ce45c37..9e8547b77 100644 --- a/xwords4/common/game.h +++ b/xwords4/common/game.h @@ -85,6 +85,15 @@ typedef struct CurGameInfo { XP_Bool confirmBTConnect; /* only used for BT */ } CurGameInfo; +typedef struct _GameStateInfo { + XP_U16 visTileCount; + XP_Bool canHint; + XP_Bool canRedo; + XP_Bool inTrade; + XP_Bool gameIsConnected; + XP_Bool canShuffle; +} GameStateInfo; + typedef struct XWGame { BoardCtxt* board; ModelCtxt* model; @@ -109,6 +118,9 @@ XP_Bool game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game, void game_saveToStream( const XWGame* game, const CurGameInfo* gi, XWStreamCtxt* stream ); void game_dispose( XWGame* game ); + +void game_getState( const XWGame* game, GameStateInfo* gsi ); + void gi_initPlayerInfo( MPFORMAL CurGameInfo* gi, const XP_UCHAR* nameTemplate ); void gi_disposePlayerInfo( MPFORMAL CurGameInfo* gi );