From da2cfa59349913edea3b607f440843ee95d78d3d Mon Sep 17 00:00:00 2001 From: eehouse Date: Thu, 15 Apr 2010 02:15:50 +0000 Subject: [PATCH] changes (commited earlier but now somehow missing) putting scroll-related fields into a struct so vertical and horizontal can be handled by the same code; add to board_zoom out params indicating whether further zooming is possible. --- xwords4/android/XWords4/jni/drawwrapper.c | 4 +- xwords4/android/XWords4/jni/utilwrapper.c | 3 +- xwords4/android/XWords4/jni/xwjni.c | 7 +- xwords4/common/board.c | 292 ++++++++++++---------- xwords4/common/board.h | 3 +- xwords4/common/boarddrw.c | 42 ++-- xwords4/common/boardp.h | 23 +- xwords4/common/dragdrpp.c | 37 ++- 8 files changed, 228 insertions(+), 183 deletions(-) diff --git a/xwords4/android/XWords4/jni/drawwrapper.c b/xwords4/android/XWords4/jni/drawwrapper.c index 8234f1ea3..816158ea2 100644 --- a/xwords4/android/XWords4/jni/drawwrapper.c +++ b/xwords4/android/XWords4/jni/drawwrapper.c @@ -223,9 +223,7 @@ static XP_Bool and_draw_boardBegin( DrawCtx* dctx, const XP_Rect* rect, XP_U16 cellWidth, XP_U16 cellHeight, DrawFocusState dfs ) { - AndDraw* draw = (AndDraw*)dctx; - XP_Bool result = NULL != draw->jdraw; - return result; + return XP_TRUE; } static XP_Bool diff --git a/xwords4/android/XWords4/jni/utilwrapper.c b/xwords4/android/XWords4/jni/utilwrapper.c index 4bd629683..97636c9c8 100644 --- a/xwords4/android/XWords4/jni/utilwrapper.c +++ b/xwords4/android/XWords4/jni/utilwrapper.c @@ -179,7 +179,8 @@ and_util_trayHiddenChange(XW_UtilCtxt* uc, XW_TrayVisState newState, } static void -and_util_yOffsetChange(XW_UtilCtxt* uc, XP_U16 oldOffset, XP_U16 newOffset ) +and_util_yOffsetChange(XW_UtilCtxt* uc, XP_U16 maxOffset, + XP_U16 oldOffset, XP_U16 newOffset ) { #if 0 AndUtil* util = (AndUtil*)uc; diff --git a/xwords4/android/XWords4/jni/xwjni.c b/xwords4/android/XWords4/jni/xwjni.c index ce64e600d..75781b008 100644 --- a/xwords4/android/XWords4/jni/xwjni.c +++ b/xwords4/android/XWords4/jni/xwjni.c @@ -510,11 +510,14 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1setPos JNIEXPORT jboolean JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_board_1zoom -( JNIEnv* env, jclass C, jint gamePtr, jint zoomBy ) +( JNIEnv* env, jclass C, jint gamePtr, jint zoomBy, jbooleanArray jCanZoom ) { jboolean result; XWJNI_START(); - result = board_zoom( state->game.board, zoomBy ); + XP_Bool canIn, canOut; + result = board_zoom( state->game.board, zoomBy, &canIn, &canOut ); + jboolean canZoom[2] = { canIn, canOut }; + setBoolArray( env, jCanZoom, VSIZE(canZoom), canZoom ); XWJNI_END(); return result; } diff --git a/xwords4/common/board.c b/xwords4/common/board.c index e4774fa09..defa77920 100644 --- a/xwords4/common/board.c +++ b/xwords4/common/board.c @@ -203,10 +203,10 @@ board_makeFromStream( MPFORMAL XWStreamCtxt* stream, ModelCtxt* model, board = board_make( MPPARM(mpool) model, server, draw, util ); if ( version >= STREAM_VERS_4YOFFSET) { - board->xOffset = (XP_U16)stream_getBits( stream, 4 ); + board->sd[SCROLL_H].offset = (XP_U16)stream_getBits( stream, 4 ); board->zoomCount = (XP_U16)stream_getBits( stream, 4 ); } - board->yOffset = (XP_U16) + board->sd[SCROLL_V].offset = (XP_U16) stream_getBits( stream, (version < STREAM_VERS_4YOFFSET) ? 2 : 4 ); board->isFlipped = (XP_Bool)stream_getBits( stream, 1 ); board->gameOver = (XP_Bool)stream_getBits( stream, 1 ); @@ -272,9 +272,9 @@ board_writeToStream( BoardCtxt* board, XWStreamCtxt* stream ) { XP_U16 nPlayers, i; - stream_putBits( stream, 4, board->xOffset ); + stream_putBits( stream, 4, board->sd[SCROLL_H].offset ); stream_putBits( stream, 4, board->zoomCount ); - stream_putBits( stream, 4, board->yOffset ); + stream_putBits( stream, 4, board->sd[SCROLL_V].offset ); stream_putBits( stream, 1, board->isFlipped ); stream_putBits( stream, 1, board->gameOver ); stream_putBits( stream, 1, board->showColors ); @@ -379,23 +379,14 @@ board_setTimerLoc( BoardCtxt* board, board->timerBounds.height = timerHeight; } /* board_setTimerLoc */ -void -board_setScale( BoardCtxt* board, XP_U16 hScale, XP_U16 vScale ) -{ - if ( hScale != board->boardHScale || vScale != board->boardVScale ) { - board->boardVScale = vScale; - board->boardHScale = hScale; - figureBoardRect( board ); - board_invalAll( board ); - } -} /* board_setScale */ - +#if 0 void board_getScale( BoardCtxt* board, XP_U16* hScale, XP_U16* vScale ) { - *hScale = board->boardHScale; - *vScale = board->boardVScale; + *hScale = board->sd[SCROLL_H].scale; + *vScale = board->sd[SCROLL_V].scale; } /* board_getScale */ +#endif XP_Bool board_prefsChanged( BoardCtxt* board, CommonPrefs* cp ) @@ -443,26 +434,31 @@ board_prefsChanged( BoardCtxt* board, CommonPrefs* cp ) XP_Bool adjustXOffset( BoardCtxt* board, XP_S16 moveBy ) { - /* XP_LOGF( "%s(%d)", __func__, moveBy ); */ - XP_U16 nCols = model_numCols(board->model); - XP_U16 nVisible = nCols - board->zoomCount; - XP_S16 newOffset = board->xOffset - moveBy; + XP_Bool changed = XP_FALSE; + if ( 0 != moveBy ) { + XP_U16 nCols = model_numCols(board->model); + XP_U16 nVisible = nCols - board->zoomCount; + ScrollData* hsd = &board->sd[SCROLL_H]; + XP_S16 newOffset = hsd->offset - moveBy; - if ( newOffset < 0 ) { - newOffset = 0; - } else if ( newOffset + nVisible > nCols ) { - newOffset = nCols - nVisible; + if ( newOffset < 0 ) { + newOffset = 0; + } else if ( newOffset + nVisible > nCols ) { + newOffset = nCols - nVisible; + } + + changed = board_setXOffset( board, newOffset ); } - - return board_setXOffset( board, newOffset ); + return changed; } /* adjustXOffset */ XP_Bool adjustYOffset( BoardCtxt* board, XP_S16 moveBy ) { - XP_U16 nVisible = board->lastVisibleRow - board->yOffset + 1; + ScrollData* vsd = &board->sd[SCROLL_V]; + XP_U16 nVisible = vsd->lastVisible - vsd->offset + 1; XP_U16 nRows = model_numRows(board->model); - XP_S16 newOffset = board->yOffset - moveBy; + XP_S16 newOffset = vsd->offset - moveBy; if ( newOffset < 0 ) { newOffset = 0; @@ -476,12 +472,12 @@ adjustYOffset( BoardCtxt* board, XP_S16 moveBy ) static XP_Bool board_setXOffset( BoardCtxt* board, XP_U16 offset ) { - XP_Bool changed = offset != board->xOffset; + ScrollData* hsd = &board->sd[SCROLL_H]; + XP_Bool changed = offset != hsd->offset; if ( changed ) { - board->xOffset = offset; - board->lastVisibleCol = model_numCols(board->model) - - board->zoomCount + offset; - XP_LOGF( "%s: lastVisibleCol=%d", __func__, board->lastVisibleCol ); + hsd->offset = offset; + hsd->lastVisible = model_numCols(board->model) + - board->zoomCount + offset - 1; board_invalAll( board ); } return changed; @@ -490,30 +486,23 @@ board_setXOffset( BoardCtxt* board, XP_U16 offset ) XP_Bool board_setYOffset( BoardCtxt* board, XP_U16 offset ) { - XP_U16 oldOffset = board->yOffset; + ScrollData* vsd = &board->sd[SCROLL_V]; + XP_U16 oldOffset = vsd->offset; XP_Bool result = oldOffset != offset; if ( result ) { - XP_U16 nVisible = board->lastVisibleRow - board->yOffset + 1; + XP_U16 nVisible = vsd->lastVisible - vsd->offset + 1; XP_U16 nRows = model_numRows(board->model); result = offset <= nRows - nVisible; if ( result ) { - /* check if scrolling makes sense for this board in its current - state. */ - XP_U16 visibleHeight = board->boardBounds.height; - XP_U16 fullHeight = nRows * board->boardVScale; - result = visibleHeight < fullHeight; - - if ( result ) { - invalSelTradeWindow( board ); - board->yOffset = offset; - figureBoardRect( board ); - util_yOffsetChange( board->util, board->maxYOffset, - oldOffset, offset ); - invalSelTradeWindow( board ); - board->needsDrawing = XP_TRUE; - } + invalSelTradeWindow( board ); + vsd->offset = offset; + figureBoardRect( board ); + util_yOffsetChange( board->util, vsd->maxOffset, + oldOffset, offset ); + invalSelTradeWindow( board ); + board->needsDrawing = XP_TRUE; } } @@ -523,7 +512,8 @@ board_setYOffset( BoardCtxt* board, XP_U16 offset ) XP_U16 board_getYOffset( const BoardCtxt* board ) { - return board->yOffset; + const ScrollData* vsd = &board->sd[SCROLL_V]; + return vsd->offset; } /* board_getYOffset */ static XP_U16 @@ -538,10 +528,12 @@ adjustOffset( XP_U16 curOffset, XP_S16 zoomBy ) } XP_Bool -board_zoom( BoardCtxt* board, XP_S16 zoomBy ) +board_zoom( BoardCtxt* board, XP_S16 zoomBy, XP_Bool* canIn, XP_Bool* canOut ) { XP_Bool changed; XP_S16 zoomCount = board->zoomCount; + ScrollData* hsd = &board->sd[SCROLL_H]; + ScrollData* vsd = &board->sd[SCROLL_V]; XP_U16 maxCount = model_numCols( board->model ) - 2; /* 2 for scrolling */ if ( board->boardBounds.width > board->boardBounds.height ) { @@ -559,13 +551,21 @@ board_zoom( BoardCtxt* board, XP_S16 zoomBy ) changed = zoomCount != board->zoomCount; if ( changed ) { /* Try to distribute the zoom */ - board->xOffset = adjustOffset( board->xOffset, zoomBy ); - board->yOffset = adjustOffset( board->yOffset, zoomBy ); + hsd->offset = adjustOffset( hsd->offset, zoomBy ); + vsd->offset = adjustOffset( vsd->offset, zoomBy ); board->zoomCount = zoomCount; figureBoardRect( board ); board_invalAll( board ); } + + if ( !!canIn ) { + *canIn = maxCount > zoomCount; + } + if ( !!canOut ) { + *canOut = zoomCount > 0; + } + return changed; } /* board_zoom */ @@ -1043,10 +1043,13 @@ board_invalAllTiles( BoardCtxt* board ) static void invalPerimeter( BoardCtxt* board ) { - XP_U16 lastCol = model_numCols( board->model ) - 1; - XP_U16 firstAndLast = (1 << lastCol) | 1; - XP_U16 firstRow = board->yOffset; - XP_U16 lastRow = board->lastVisibleRow; + ScrollData* hsd = &board->sd[SCROLL_H]; + XP_U16 firstCol = hsd->offset; + XP_U16 lastCol = hsd->lastVisible; + XP_U16 firstAndLast = (1 << lastCol) | (1 << firstCol); + ScrollData* vsd = &board->sd[SCROLL_V]; + XP_U16 firstRow = vsd->offset; + XP_U16 lastRow = vsd->lastVisible; /* top and bottom rows */ board->redrawFlags[firstRow] = ~0; @@ -1140,42 +1143,46 @@ invalCellsWithTiles( BoardCtxt* board ) return board->needsDrawing; } /* invalCellsWithTiles */ -XP_Bool -checkScrollCell( BoardCtxt* board, XP_U16 col, XP_U16 row ) +static XP_S16 +figureOffset(const BoardCtxt* board, SDIndex indx, XP_U16 col ) { - XP_Rect rect; - XP_Bool moved = XP_FALSE; - - if ( board->boardObscuresTray && board->trayVisState != TRAY_HIDDEN ) { - /* call getCellRect until the cell's on the board. */ - while ( !getCellRect( board, col, row, &rect ) ) { - XP_S16 moveBy = 1; - if ( rect.top < board->boardBounds.top ) { - /* do nothing; set to 1 above to prevent warning */ - } else if ( rect.top + rect.height > - board->boardBounds.top + board->boardBounds.height ) { - moveBy = -1; - } else { - /* what if a horizontal scroll's what's needed? */ - XP_ASSERT( 0 ); - } - moved = adjustYOffset( board, moveBy ); - XP_ASSERT( moved ); - } - } - return moved; -} /* checkScrollCell */ + XP_S16 offset = 0; + const ScrollData* sd = &board->sd[indx]; + if ( col < sd->offset ) { + offset = sd->offset - col; + } else if ( col > sd->lastVisible ) { + offset = sd->lastVisible - col; + } + return offset; +} XP_Bool -onBorderCanScroll( const BoardCtxt* board, XP_U16 row, XP_S16* changeP ) +scrollIntoView( BoardCtxt* board, XP_U16 col, XP_U16 row ) +{ + XP_Bool moved; + XP_S16 newOffset; + + newOffset = figureOffset( board, SCROLL_H, col ); + moved = adjustXOffset( board, newOffset ); + + newOffset = figureOffset( board, SCROLL_V, row ); + moved = adjustYOffset( board, newOffset ) || moved; + + return moved; +} /* scrollIntoView */ + +XP_Bool +onBorderCanScroll( const BoardCtxt* board, SDIndex indx, + XP_U16 row /*or col */, XP_S16* changeP ) { XP_Bool result; XP_S16 change = 0; - XP_U16 yOffset = board_getYOffset( board ); + const ScrollData* sd = &board->sd[indx]; + XP_U16 offset = sd->offset; - if ( yOffset > 0 && row == yOffset ) { - change = -yOffset; - } else if ( row == board->lastVisibleRow ) { + if ( offset > 0 && row == offset ) { + change = -offset; + } else if ( row == sd->lastVisible ) { XP_U16 lastRow = model_numRows(board->model) - 1; change = lastRow - row; } @@ -1349,6 +1356,7 @@ setTrayVisState( BoardCtxt* board, XW_TrayVisState newState ) XP_Bool nowHidden = newState == TRAY_HIDDEN; XP_U16 selPlayer = board->selPlayer; XP_U16 nVisible; + ScrollData* vsd = &board->sd[SCROLL_V]; /* redraw cells that are pending; whether tile is visible may change */ @@ -1391,7 +1399,7 @@ setTrayVisState( BoardCtxt* board, XW_TrayVisState newState ) invalCurHintRect( board, selPlayer ); #endif - nVisible = board->lastVisibleRow - board->yOffset + 1; + nVisible = vsd->lastVisible - vsd->offset + 1; util_trayHiddenChange( board->util, board->trayVisState, nVisible ); } return changed; @@ -1610,22 +1618,28 @@ board_requestHint( BoardCtxt* board, return result || redraw; } /* board_requestHint */ -static void +static XP_Bool figureDims( XP_U16* edges, XP_U16 len, XP_U16 nVisible, XP_U16 increment, XP_U16 extra ) { + XP_Bool changed = XP_FALSE; XP_U16 ii; XP_U16 nAtStart = extra % nVisible; increment += extra / nVisible; for ( ii = 0; ii < len; ++ii ) { - edges[ii] = increment; + XP_U16 newVal = increment; if ( ii % nVisible < nAtStart ) { - ++edges[ii]; + ++newVal; + } + if ( edges[ii] != newVal ) { + edges[ii] = newVal; + changed = XP_TRUE; } } -} + return changed; +} /* figureDims */ static XP_U16 figureHScale( BoardCtxt* board ) @@ -1636,14 +1650,17 @@ figureHScale( BoardCtxt* board ) XP_U16 spares = board->boardBounds.width % nVisCols; XP_U16 maxOffset = nCols - nVisCols; - if ( board->xOffset > maxOffset ) { - board->xOffset = maxOffset; + ScrollData* hsd = &board->sd[SCROLL_H]; + if ( hsd->offset > maxOffset ) { + hsd->offset = maxOffset; } - board->lastVisibleCol = nCols - board->zoomCount + board->xOffset - 1; + hsd->lastVisible = nCols - board->zoomCount + hsd->offset - 1; - figureDims( board->colWidths, VSIZE(board->colWidths), nVisCols, - scale, spares ); + if ( figureDims( hsd->dims, VSIZE(hsd->dims), nVisCols, + scale, spares ) ) { + board_invalAll( board ); + } return scale; } /* figureHScale */ @@ -1656,10 +1673,12 @@ figureBoardRect( BoardCtxt* board ) XP_U16 nVisible; XP_U16 nRows = model_numRows( board->model ); XP_U16 boardScale = figureHScale( board ); + ScrollData* hsd = &board->sd[SCROLL_H]; + ScrollData* vsd = &board->sd[SCROLL_V]; - if ( boardScale != board->boardHScale ) { + if ( boardScale != hsd->scale ) { board_invalAll( board ); - board->boardHScale = boardScale; + hsd->scale = boardScale; } /* Figure height of board. Max height is with all rows visible and @@ -1675,46 +1694,45 @@ figureBoardRect( BoardCtxt* board ) maxHeight = board->trayBounds.top - board->boardBounds.top; } XP_U16 extra; + XP_U16 oldYOffset = vsd->offset; if ( wantHeight <= maxHeight ) { /* yay! No need to scale */ - board->boardVScale = maxHeight / nRows; + vsd->scale = maxHeight / nRows; extra = maxHeight % nRows; boardBounds.height = maxHeight; board->boardObscuresTray = XP_FALSE; - board->yOffset = 0; + vsd->offset = 0; nVisible = nRows; } else { XP_S16 maxYOffset; - XP_U16 oldYOffset = board->yOffset; XP_Bool yChanged = XP_TRUE; /* Need to hide rows etc. */ boardBounds.height = maxHeight; - board->boardVScale = boardScale; + vsd->scale = boardScale; nVisible = maxHeight / boardScale; extra = maxHeight % boardScale; maxYOffset = nRows - nVisible; - if ( board->yOffset > maxYOffset ) { - board->yOffset = maxYOffset; - } else if ( maxYOffset != board->maxYOffset ) { - board->maxYOffset = maxYOffset; + if ( vsd->offset > maxYOffset ) { + vsd->offset = maxYOffset; + } else if ( maxYOffset != vsd->maxOffset ) { + vsd->maxOffset = maxYOffset; } else { yChanged = XP_FALSE; } - if ( yChanged ) { - util_yOffsetChange( board->util, maxYOffset, oldYOffset, - board->yOffset ); - } - /* XP_LOGF( "%s: maxYOffset: %d; board->yOffset: %d", __func__, */ - /* board->maxYOffset, board->yOffset ); */ - - board->boardObscuresTray = !trayHidden; + board->boardObscuresTray = board->trayBounds.top < wantHeight + && board->trayBounds.left < (boardBounds.left + boardBounds.width); } - board->lastVisibleRow = nVisible + board->yOffset - 1; + util_yOffsetChange( board->util, nRows - nVisible, oldYOffset, + vsd->offset ); - figureDims( board->rowHeights, VSIZE(board->rowHeights), nVisible, - board->boardVScale, extra ); + vsd->lastVisible = nVisible + vsd->offset - 1; + + if ( figureDims( vsd->dims, VSIZE(vsd->dims), nVisible, + vsd->scale, extra ) ) { + board_invalAll( board ); + } board->boardBounds = boardBounds; } @@ -1740,12 +1758,14 @@ coordToCell( BoardCtxt* board, XP_S16 xx, XP_S16 yy, XP_U16* colP, XP_U16 maxCols = model_numCols( board->model ); XP_S16 gotCol = -1; XP_S16 gotRow = -1; + ScrollData* hsd = &board->sd[SCROLL_H]; + ScrollData* vsd = &board->sd[SCROLL_V]; xx -= board->boardBounds.left; XP_ASSERT( xx >= 0 ); - for ( col = board->xOffset; col < maxCols; ++col ) { - xx -= board->colWidths[col]; + for ( col = hsd->offset; col < maxCols; ++col ) { + xx -= hsd->dims[col]; if ( xx < 0 ) { gotCol = col; break; @@ -1754,8 +1774,8 @@ coordToCell( BoardCtxt* board, XP_S16 xx, XP_S16 yy, XP_U16* colP, yy -= board->boardBounds.top; XP_ASSERT( yy >= 0 ); - for ( row = board->yOffset; row < maxCols; ++row ) { - yy -= board->rowHeights[col]; + for ( row = vsd->offset; row < maxCols; ++row ) { + yy -= vsd->dims[col]; if ( yy < 0 ) { gotRow = row; break; @@ -1783,20 +1803,22 @@ XP_Bool getCellRect( const BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Rect* rect ) { XP_U16 cur; - XP_Bool onBoard = col >= board->xOffset && row >= board->yOffset - && col <= board->lastVisibleCol && row <= board->lastVisibleRow; + const ScrollData* hsd = &board->sd[SCROLL_H]; + const ScrollData* vsd = &board->sd[SCROLL_V]; + XP_Bool onBoard = col >= hsd->offset && row >= vsd->offset + && col <= hsd->lastVisible && row <= vsd->lastVisible; rect->left = board->boardBounds.left; - for ( cur = board->xOffset; cur < col; ++cur ) { - rect->left += board->colWidths[cur]; + for ( cur = hsd->offset; cur < col; ++cur ) { + rect->left += hsd->dims[cur]; } - rect->width = board->colWidths[col]; + rect->width = hsd->dims[col]; rect->top = board->boardBounds.top; - for ( cur = board->yOffset; cur < row; ++cur ) { - rect->top += board->rowHeights[cur]; + for ( cur = vsd->offset; cur < row; ++cur ) { + rect->top += vsd->dims[cur]; } - rect->height = board->rowHeights[row]; + rect->height = vsd->dims[row]; return onBoard; } /* getCellRect */ @@ -2629,7 +2651,7 @@ invalFocusOwner( BoardCtxt* board ) if ( board->focusHasDived ) { BdCursorLoc loc = pti->bdCursor; invalCell( board, loc.col, loc.row ); - checkScrollCell( board, loc.col, loc.row ); + scrollIntoView( board, loc.col, loc.row ); } else { #ifdef PERIMETER_FOCUS invalPerimeter( board ); @@ -2886,7 +2908,7 @@ board_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly, loc.col = col; loc.row = row; pti->bdCursor = loc; - checkScrollCell( board, col, row ); + scrollIntoView( board, col, row ); } return changed; } /* board_moveCursor */ @@ -3045,7 +3067,7 @@ setArrowFor( BoardCtxt* board, XP_U16 player, XP_U16 col, XP_U16 row ) arrow->col = (XP_U8)col; arrow->row = (XP_U8)row; - checkScrollCell( board, col, row ); + scrollIntoView( board, col, row ); } /* setArrowFor */ static void @@ -3134,7 +3156,7 @@ boardCellChanged( void* p_board, XP_U16 turn, XP_U16 modelCol, XP_U16 modelRow, } } - checkScrollCell( board, col, row ); + scrollIntoView( board, col, row ); } invalCell( (BoardCtxt*)p_board, col, row ); diff --git a/xwords4/common/board.h b/xwords4/common/board.h index d645636e2..3bf7f7617 100644 --- a/xwords4/common/board.h +++ b/xwords4/common/board.h @@ -77,7 +77,8 @@ void board_reset( BoardCtxt* board ); XP_Bool board_setYOffset( BoardCtxt* board, XP_U16 newOffset ); XP_U16 board_getYOffset( const BoardCtxt* board ); -XP_Bool board_zoom( BoardCtxt* board, XP_S16 zoomBy ); +XP_Bool board_zoom( BoardCtxt* board, XP_S16 zoomBy, XP_Bool* canIn, + XP_Bool* canOut ); void board_setScoreboardLoc( BoardCtxt* board, XP_U16 scoreLeft, XP_U16 scoreTop, diff --git a/xwords4/common/boarddrw.c b/xwords4/common/boarddrw.c index a1fc8376c..da9038f27 100644 --- a/xwords4/common/boarddrw.c +++ b/xwords4/common/boarddrw.c @@ -95,15 +95,16 @@ invalOldPerimeter( BoardCtxt* board ) { /* We need to inval the center of the row that's moving into the center from a border (at which point it got borders drawn on it.) */ - XP_S16 diff = board->yOffset - board->prevYScrollOffset; + ScrollData* vsd = &board->sd[SCROLL_V]; + XP_S16 diff = vsd->offset - board->prevYScrollOffset; XP_U16 firstRow, lastRow; XP_ASSERT( diff != 0 ); if ( diff < 0 ) { /* moving up; inval row previously on bottom */ - firstRow = board->yOffset + 1; + firstRow = vsd->offset + 1; lastRow = board->prevYScrollOffset; } else { - XP_U16 nVisible = board->lastVisibleRow - board->yOffset + 1; + XP_U16 nVisible = vsd->lastVisible - vsd->offset + 1; lastRow = board->prevYScrollOffset + nVisible - 1; firstRow = lastRow - diff + 1; } @@ -232,9 +233,9 @@ static void drawBoard( BoardCtxt* board ) { if ( board->needsDrawing - && draw_boardBegin( board->draw, - &board->boardBounds, - board->boardHScale, board->boardVScale, + && draw_boardBegin( board->draw, &board->boardBounds, + board->sd[SCROLL_H].scale, + board->sd[SCROLL_V].scale, dfsFor( board, OBJ_BOARD ) ) ) { XP_Bool allDrawn = XP_TRUE; @@ -242,6 +243,8 @@ drawBoard( BoardCtxt* board ) XP_S16 col, row, nVisCols; ModelCtxt* model = board->model; BoardArrow const* arrow = NULL; + ScrollData* hsd = &board->sd[SCROLL_H]; + ScrollData* vsd = &board->sd[SCROLL_V]; BlankQueue bq; scrollIfCan( board ); /* this must happen before we count blanks @@ -270,14 +273,14 @@ drawBoard( BoardCtxt* board ) } nVisCols = model_numCols( model ) - board->zoomCount; - for ( row = board->yOffset; row <= board->lastVisibleRow; ++row ) { + for ( row = vsd->offset; row <= vsd->lastVisible; ++row ) { XP_U16 rowFlags = board->redrawFlags[row]; if ( rowFlags != 0 ) { XP_U16 failedBits = 0; for ( col = 0; col < nVisCols; ++col ) { - XP_U16 colMask = 1 << (col + board->xOffset); + XP_U16 colMask = 1 << (col + hsd->offset); if ( 0 != (rowFlags & colMask) ) { - if ( !drawCell( board, col + board->xOffset, + if ( !drawCell( board, col + hsd->offset, row, XP_TRUE )) { failedBits |= colMask; allDrawn = XP_FALSE; @@ -451,7 +454,8 @@ static XP_Bool cellFocused( const BoardCtxt* board, XP_U16 col, XP_U16 row ) { XP_Bool focussed = XP_FALSE; - + const ScrollData* hsd = &board->sd[SCROLL_H]; + const ScrollData* vsd = &board->sd[SCROLL_V]; if ( (board->focussed == OBJ_BOARD) && !board->hideFocus ) { if ( board->focusHasDived ) { if ( (col == board->selInfo->bdCursor.col) @@ -460,10 +464,10 @@ cellFocused( const BoardCtxt* board, XP_U16 col, XP_U16 row ) } } else { #ifdef PERIMETER_FOCUS - focussed = (col == 0) - || (col == model_numCols(board->model) - 1) - || (row == board->yOffset) - || (row == board->lastVisibleRow); + focussed = (col == hsd->offset) + || (col == hsd->lastVisible) + || (row == vsd->offset) + || (row == vsd->lastVisible); #else focussed = XP_TRUE; #endif @@ -513,6 +517,7 @@ drawDragTileIf( BoardCtxt* board ) static XP_S16 sumRowHeights( const BoardCtxt* board, XP_U16 row1, XP_U16 row2 ) { + const ScrollData* vsd = &board->sd[SCROLL_V]; XP_S16 sign = row1 > row2 ? -1 : 1; XP_S16 result, ii; if ( sign < 0 ) { @@ -521,7 +526,7 @@ sumRowHeights( const BoardCtxt* board, XP_U16 row1, XP_U16 row2 ) row2 = tmp; } for ( result = 0, ii = row1; ii < row2; ++ii ) { - result += board->rowHeights[ii]; + result += vsd->dims[ii]; } return result * sign; } @@ -529,7 +534,8 @@ sumRowHeights( const BoardCtxt* board, XP_U16 row1, XP_U16 row2 ) static void scrollIfCan( BoardCtxt* board ) { - if ( board->yOffset != board->prevYScrollOffset ) { + ScrollData* vsd = &board->sd[SCROLL_V]; + if ( vsd->offset != board->prevYScrollOffset ) { XP_Rect scrollR = board->boardBounds; XP_Bool scrolled; XP_S16 dist; @@ -543,7 +549,7 @@ scrollIfCan( BoardCtxt* board ) #endif invalSelTradeWindow( board ); - dist = sumRowHeights( board, board->prevYScrollOffset, board->yOffset ); + dist = sumRowHeights( board, board->prevYScrollOffset, vsd->offset ); scrolled = draw_vertScrollBoard( board->draw, &scrollR, dist, dfsFor( board, OBJ_BOARD ) ); @@ -555,7 +561,7 @@ scrollIfCan( BoardCtxt* board ) } else { board_invalAll( board ); } - board->prevYScrollOffset = board->yOffset; + board->prevYScrollOffset = vsd->offset; } } /* scrollIfCan */ diff --git a/xwords4/common/boardp.h b/xwords4/common/boardp.h index 0eff6f131..53f68e30a 100644 --- a/xwords4/common/boardp.h +++ b/xwords4/common/boardp.h @@ -116,6 +116,14 @@ typedef struct _PerTurnInfo { #endif } PerTurnInfo; +typedef struct _ScrollData { + XP_U16 scale; + XP_U16 offset; + XP_U16 maxOffset; + XP_U16 lastVisible; + XP_U16 dims[MAX_COLS]; +} ScrollData; +typedef enum { SCROLL_H, SCROLL_V, N_SCROLL_DIMS } SDIndex; struct BoardCtxt { /* BoardVTable* vtable; */ @@ -125,14 +133,8 @@ struct BoardCtxt { XW_UtilCtxt* util; struct CurGameInfo* gi; + ScrollData sd[N_SCROLL_DIMS]; - XP_U16 boardHScale; - XP_U16 boardVScale; - XP_U16 xOffset; - XP_U16 yOffset; - XP_U16 maxYOffset; - XP_U16 lastVisibleRow; - XP_U16 lastVisibleCol; XP_U16 preHideYOffset; XP_U16 prevYScrollOffset; /* represents where the last draw took place; used to see if bit scrolling can be used */ @@ -171,8 +173,6 @@ struct BoardCtxt { XP_U16 star_row; XP_U16 zoomCount; - XP_U16 colWidths[MAX_COLS]; - XP_U16 rowHeights[MAX_COLS]; /* Unless KEYBOARD_NAV is defined, this does not change */ BoardObjectType focussed; @@ -284,8 +284,9 @@ const XP_UCHAR* getTileDrawInfo( const BoardCtxt* board, Tile tile, XP_S16* value ); XP_Bool dividerMoved( BoardCtxt* board, XP_U8 newLoc ); -XP_Bool checkScrollCell( BoardCtxt* board, XP_U16 col, XP_U16 row ); -XP_Bool onBorderCanScroll( const BoardCtxt* board, XP_U16 row, XP_S16* change ); +XP_Bool scrollIntoView( BoardCtxt* board, XP_U16 col, XP_U16 row ); +XP_Bool onBorderCanScroll( const BoardCtxt* board, SDIndex indx, XP_U16 row, + XP_S16* change ); XP_Bool adjustXOffset( BoardCtxt* board, XP_S16 moveBy ); XP_Bool adjustYOffset( BoardCtxt* board, XP_S16 moveBy ); diff --git a/xwords4/common/dragdrpp.c b/xwords4/common/dragdrpp.c index e585ad820..29109a6ea 100644 --- a/xwords4/common/dragdrpp.c +++ b/xwords4/common/dragdrpp.c @@ -27,7 +27,7 @@ extern "C" { /* How many squares must scroll gesture take in to be recognized. */ #ifndef SCROLL_DRAG_THRESHHOLD -# define SCROLL_DRAG_THRESHHOLD 3 +# define SCROLL_DRAG_THRESHHOLD 1 #endif static XP_Bool dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy, @@ -86,7 +86,8 @@ ddStartBoard( BoardCtxt* board, XP_U16 xx, XP_U16 yy ) then the alt key determines it. I figure scrolling will be more common than hint dragging when both are possible, but you can turn hint dragging off, so if it's on that's probably what you want. */ - XP_Bool canScroll = board->lastVisibleRow < model_numRows(board->model); + ScrollData* vsd = &board->sd[SCROLL_V]; + XP_Bool canScroll = vsd->lastVisible < model_numRows(board->model); if ( 0 ) { #ifdef XWFEATURE_SEARCHLIMIT } else if ( !board->gi->hintsNotAllowed && board->gi->allowHintRect @@ -467,13 +468,13 @@ dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy, #endif } else if ( ds->dtype == DT_BOARD ) { if ( newInfo.obj == OBJ_BOARD ) { - XP_S16 diff = newInfo.u.board.row - ds->cur.u.board.row; + XP_S16 diff = newInfo.u.board.col - ds->cur.u.board.col; diff /= SCROLL_DRAG_THRESHHOLD; - moving = adjustYOffset( board, diff ); + moving = adjustXOffset( board, diff ); - diff = newInfo.u.board.col - ds->cur.u.board.col; + diff = newInfo.u.board.row - ds->cur.u.board.row; diff /= SCROLL_DRAG_THRESHHOLD; - moving = adjustXOffset( board, diff ) || moving; + moving = adjustYOffset( board, diff ) || moving; } } else { if ( newInfo.obj == OBJ_BOARD ) { @@ -572,13 +573,23 @@ scrollTimerProc( void* closure, XWTimerReason XP_UNUSED_DBG(why) ) XP_ASSERT( why == TIMER_PENDOWN ); if ( ds->scrollTimerSet ) { - XP_S16 change; + XP_S16 changeX = 0; + XP_S16 changeY = 0; ds->scrollTimerSet = XP_FALSE; - if ( onBorderCanScroll( board, ds->cur.u.board.row, &change ) ) { + XP_Bool canScroll = onBorderCanScroll( board, SCROLL_H, + ds->cur.u.board.col, &changeX ); + canScroll = onBorderCanScroll( board, SCROLL_V, ds->cur.u.board.row, + &changeY ) || canScroll; + if ( canScroll ) { invalDragObj( board, &ds->cur ); - ds->cur.u.board.row += (change >0 ? 1 : -1); - if ( checkScrollCell( board, ds->cur.u.board.col, - ds->cur.u.board.row ) ) { + if ( 0 != changeX ) { + ds->cur.u.board.col += (changeX >0 ? 1 : -1); + } + if ( 0 != changeY ) { + ds->cur.u.board.row += (changeY >0 ? 1 : -1); + } + if ( scrollIntoView( board, ds->cur.u.board.col, + ds->cur.u.board.row ) ) { board_draw( board ); /* may fail, e.g. on wince */ startScrollTimerIf( board ); draw = XP_TRUE; @@ -595,7 +606,9 @@ startScrollTimerIf( BoardCtxt* board ) if ( (ds->dtype == DT_TILE) && (ds->cur.obj == OBJ_BOARD) ) { XP_S16 ignore; - if ( onBorderCanScroll( board, ds->cur.u.board.row, &ignore ) ) { + if ( onBorderCanScroll( board, SCROLL_H, ds->cur.u.board.col, &ignore ) + || onBorderCanScroll( board, SCROLL_V, ds->cur.u.board.row, + &ignore ) ) { util_setTimer( board->util, TIMER_PENDOWN, 0, scrollTimerProc, (void*) board ); ds->scrollTimerSet = XP_TRUE;