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.
This commit is contained in:
eehouse 2010-04-15 02:15:50 +00:00
parent 477899e6aa
commit da2cfa5934
8 changed files with 228 additions and 183 deletions

View file

@ -223,9 +223,7 @@ static XP_Bool
and_draw_boardBegin( DrawCtx* dctx, const XP_Rect* rect, and_draw_boardBegin( DrawCtx* dctx, const XP_Rect* rect,
XP_U16 cellWidth, XP_U16 cellHeight, DrawFocusState dfs ) XP_U16 cellWidth, XP_U16 cellHeight, DrawFocusState dfs )
{ {
AndDraw* draw = (AndDraw*)dctx; return XP_TRUE;
XP_Bool result = NULL != draw->jdraw;
return result;
} }
static XP_Bool static XP_Bool

View file

@ -179,7 +179,8 @@ and_util_trayHiddenChange(XW_UtilCtxt* uc, XW_TrayVisState newState,
} }
static void 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 #if 0
AndUtil* util = (AndUtil*)uc; AndUtil* util = (AndUtil*)uc;

View file

@ -510,11 +510,14 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1setPos
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_board_1zoom 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; jboolean result;
XWJNI_START(); 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(); XWJNI_END();
return result; return result;
} }

View file

@ -203,10 +203,10 @@ board_makeFromStream( MPFORMAL XWStreamCtxt* stream, ModelCtxt* model,
board = board_make( MPPARM(mpool) model, server, draw, util ); board = board_make( MPPARM(mpool) model, server, draw, util );
if ( version >= STREAM_VERS_4YOFFSET) { 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->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 ); stream_getBits( stream, (version < STREAM_VERS_4YOFFSET) ? 2 : 4 );
board->isFlipped = (XP_Bool)stream_getBits( stream, 1 ); board->isFlipped = (XP_Bool)stream_getBits( stream, 1 );
board->gameOver = (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; 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->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->isFlipped );
stream_putBits( stream, 1, board->gameOver ); stream_putBits( stream, 1, board->gameOver );
stream_putBits( stream, 1, board->showColors ); stream_putBits( stream, 1, board->showColors );
@ -379,23 +379,14 @@ board_setTimerLoc( BoardCtxt* board,
board->timerBounds.height = timerHeight; board->timerBounds.height = timerHeight;
} /* board_setTimerLoc */ } /* board_setTimerLoc */
void #if 0
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 */
void void
board_getScale( BoardCtxt* board, XP_U16* hScale, XP_U16* vScale ) board_getScale( BoardCtxt* board, XP_U16* hScale, XP_U16* vScale )
{ {
*hScale = board->boardHScale; *hScale = board->sd[SCROLL_H].scale;
*vScale = board->boardVScale; *vScale = board->sd[SCROLL_V].scale;
} /* board_getScale */ } /* board_getScale */
#endif
XP_Bool XP_Bool
board_prefsChanged( BoardCtxt* board, CommonPrefs* cp ) board_prefsChanged( BoardCtxt* board, CommonPrefs* cp )
@ -443,26 +434,31 @@ board_prefsChanged( BoardCtxt* board, CommonPrefs* cp )
XP_Bool XP_Bool
adjustXOffset( BoardCtxt* board, XP_S16 moveBy ) adjustXOffset( BoardCtxt* board, XP_S16 moveBy )
{ {
/* XP_LOGF( "%s(%d)", __func__, moveBy ); */ XP_Bool changed = XP_FALSE;
XP_U16 nCols = model_numCols(board->model); if ( 0 != moveBy ) {
XP_U16 nVisible = nCols - board->zoomCount; XP_U16 nCols = model_numCols(board->model);
XP_S16 newOffset = board->xOffset - moveBy; XP_U16 nVisible = nCols - board->zoomCount;
ScrollData* hsd = &board->sd[SCROLL_H];
XP_S16 newOffset = hsd->offset - moveBy;
if ( newOffset < 0 ) { if ( newOffset < 0 ) {
newOffset = 0; newOffset = 0;
} else if ( newOffset + nVisible > nCols ) { } else if ( newOffset + nVisible > nCols ) {
newOffset = nCols - nVisible; newOffset = nCols - nVisible;
}
changed = board_setXOffset( board, newOffset );
} }
return changed;
return board_setXOffset( board, newOffset );
} /* adjustXOffset */ } /* adjustXOffset */
XP_Bool XP_Bool
adjustYOffset( BoardCtxt* board, XP_S16 moveBy ) 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_U16 nRows = model_numRows(board->model);
XP_S16 newOffset = board->yOffset - moveBy; XP_S16 newOffset = vsd->offset - moveBy;
if ( newOffset < 0 ) { if ( newOffset < 0 ) {
newOffset = 0; newOffset = 0;
@ -476,12 +472,12 @@ adjustYOffset( BoardCtxt* board, XP_S16 moveBy )
static XP_Bool static XP_Bool
board_setXOffset( BoardCtxt* board, XP_U16 offset ) 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 ) { if ( changed ) {
board->xOffset = offset; hsd->offset = offset;
board->lastVisibleCol = model_numCols(board->model) hsd->lastVisible = model_numCols(board->model)
- board->zoomCount + offset; - board->zoomCount + offset - 1;
XP_LOGF( "%s: lastVisibleCol=%d", __func__, board->lastVisibleCol );
board_invalAll( board ); board_invalAll( board );
} }
return changed; return changed;
@ -490,30 +486,23 @@ board_setXOffset( BoardCtxt* board, XP_U16 offset )
XP_Bool XP_Bool
board_setYOffset( BoardCtxt* board, XP_U16 offset ) 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; XP_Bool result = oldOffset != offset;
if ( result ) { 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); XP_U16 nRows = model_numRows(board->model);
result = offset <= nRows - nVisible; result = offset <= nRows - nVisible;
if ( result ) { if ( result ) {
/* check if scrolling makes sense for this board in its current invalSelTradeWindow( board );
state. */ vsd->offset = offset;
XP_U16 visibleHeight = board->boardBounds.height; figureBoardRect( board );
XP_U16 fullHeight = nRows * board->boardVScale; util_yOffsetChange( board->util, vsd->maxOffset,
result = visibleHeight < fullHeight; oldOffset, offset );
invalSelTradeWindow( board );
if ( result ) { board->needsDrawing = XP_TRUE;
invalSelTradeWindow( board );
board->yOffset = offset;
figureBoardRect( board );
util_yOffsetChange( board->util, board->maxYOffset,
oldOffset, offset );
invalSelTradeWindow( board );
board->needsDrawing = XP_TRUE;
}
} }
} }
@ -523,7 +512,8 @@ board_setYOffset( BoardCtxt* board, XP_U16 offset )
XP_U16 XP_U16
board_getYOffset( const BoardCtxt* board ) board_getYOffset( const BoardCtxt* board )
{ {
return board->yOffset; const ScrollData* vsd = &board->sd[SCROLL_V];
return vsd->offset;
} /* board_getYOffset */ } /* board_getYOffset */
static XP_U16 static XP_U16
@ -538,10 +528,12 @@ adjustOffset( XP_U16 curOffset, XP_S16 zoomBy )
} }
XP_Bool 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_Bool changed;
XP_S16 zoomCount = board->zoomCount; 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 */ XP_U16 maxCount = model_numCols( board->model ) - 2; /* 2 for scrolling */
if ( board->boardBounds.width > board->boardBounds.height ) { if ( board->boardBounds.width > board->boardBounds.height ) {
@ -559,13 +551,21 @@ board_zoom( BoardCtxt* board, XP_S16 zoomBy )
changed = zoomCount != board->zoomCount; changed = zoomCount != board->zoomCount;
if ( changed ) { if ( changed ) {
/* Try to distribute the zoom */ /* Try to distribute the zoom */
board->xOffset = adjustOffset( board->xOffset, zoomBy ); hsd->offset = adjustOffset( hsd->offset, zoomBy );
board->yOffset = adjustOffset( board->yOffset, zoomBy ); vsd->offset = adjustOffset( vsd->offset, zoomBy );
board->zoomCount = zoomCount; board->zoomCount = zoomCount;
figureBoardRect( board ); figureBoardRect( board );
board_invalAll( board ); board_invalAll( board );
} }
if ( !!canIn ) {
*canIn = maxCount > zoomCount;
}
if ( !!canOut ) {
*canOut = zoomCount > 0;
}
return changed; return changed;
} /* board_zoom */ } /* board_zoom */
@ -1043,10 +1043,13 @@ board_invalAllTiles( BoardCtxt* board )
static void static void
invalPerimeter( BoardCtxt* board ) invalPerimeter( BoardCtxt* board )
{ {
XP_U16 lastCol = model_numCols( board->model ) - 1; ScrollData* hsd = &board->sd[SCROLL_H];
XP_U16 firstAndLast = (1 << lastCol) | 1; XP_U16 firstCol = hsd->offset;
XP_U16 firstRow = board->yOffset; XP_U16 lastCol = hsd->lastVisible;
XP_U16 lastRow = board->lastVisibleRow; 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 */ /* top and bottom rows */
board->redrawFlags[firstRow] = ~0; board->redrawFlags[firstRow] = ~0;
@ -1140,42 +1143,46 @@ invalCellsWithTiles( BoardCtxt* board )
return board->needsDrawing; return board->needsDrawing;
} /* invalCellsWithTiles */ } /* invalCellsWithTiles */
XP_Bool static XP_S16
checkScrollCell( BoardCtxt* board, XP_U16 col, XP_U16 row ) figureOffset(const BoardCtxt* board, SDIndex indx, XP_U16 col )
{ {
XP_Rect rect; XP_S16 offset = 0;
XP_Bool moved = XP_FALSE; const ScrollData* sd = &board->sd[indx];
if ( col < sd->offset ) {
if ( board->boardObscuresTray && board->trayVisState != TRAY_HIDDEN ) { offset = sd->offset - col;
/* call getCellRect until the cell's on the board. */ } else if ( col > sd->lastVisible ) {
while ( !getCellRect( board, col, row, &rect ) ) { offset = sd->lastVisible - col;
XP_S16 moveBy = 1; }
if ( rect.top < board->boardBounds.top ) { return offset;
/* 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_Bool 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_Bool result;
XP_S16 change = 0; 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 ) { if ( offset > 0 && row == offset ) {
change = -yOffset; change = -offset;
} else if ( row == board->lastVisibleRow ) { } else if ( row == sd->lastVisible ) {
XP_U16 lastRow = model_numRows(board->model) - 1; XP_U16 lastRow = model_numRows(board->model) - 1;
change = lastRow - row; change = lastRow - row;
} }
@ -1349,6 +1356,7 @@ setTrayVisState( BoardCtxt* board, XW_TrayVisState newState )
XP_Bool nowHidden = newState == TRAY_HIDDEN; XP_Bool nowHidden = newState == TRAY_HIDDEN;
XP_U16 selPlayer = board->selPlayer; XP_U16 selPlayer = board->selPlayer;
XP_U16 nVisible; XP_U16 nVisible;
ScrollData* vsd = &board->sd[SCROLL_V];
/* redraw cells that are pending; whether tile is visible may /* redraw cells that are pending; whether tile is visible may
change */ change */
@ -1391,7 +1399,7 @@ setTrayVisState( BoardCtxt* board, XW_TrayVisState newState )
invalCurHintRect( board, selPlayer ); invalCurHintRect( board, selPlayer );
#endif #endif
nVisible = board->lastVisibleRow - board->yOffset + 1; nVisible = vsd->lastVisible - vsd->offset + 1;
util_trayHiddenChange( board->util, board->trayVisState, nVisible ); util_trayHiddenChange( board->util, board->trayVisState, nVisible );
} }
return changed; return changed;
@ -1610,22 +1618,28 @@ board_requestHint( BoardCtxt* board,
return result || redraw; return result || redraw;
} /* board_requestHint */ } /* board_requestHint */
static void static XP_Bool
figureDims( XP_U16* edges, XP_U16 len, XP_U16 nVisible, figureDims( XP_U16* edges, XP_U16 len, XP_U16 nVisible,
XP_U16 increment, XP_U16 extra ) XP_U16 increment, XP_U16 extra )
{ {
XP_Bool changed = XP_FALSE;
XP_U16 ii; XP_U16 ii;
XP_U16 nAtStart = extra % nVisible; XP_U16 nAtStart = extra % nVisible;
increment += extra / nVisible; increment += extra / nVisible;
for ( ii = 0; ii < len; ++ii ) { for ( ii = 0; ii < len; ++ii ) {
edges[ii] = increment; XP_U16 newVal = increment;
if ( ii % nVisible < nAtStart ) { if ( ii % nVisible < nAtStart ) {
++edges[ii]; ++newVal;
}
if ( edges[ii] != newVal ) {
edges[ii] = newVal;
changed = XP_TRUE;
} }
} }
} return changed;
} /* figureDims */
static XP_U16 static XP_U16
figureHScale( BoardCtxt* board ) figureHScale( BoardCtxt* board )
@ -1636,14 +1650,17 @@ figureHScale( BoardCtxt* board )
XP_U16 spares = board->boardBounds.width % nVisCols; XP_U16 spares = board->boardBounds.width % nVisCols;
XP_U16 maxOffset = nCols - nVisCols; XP_U16 maxOffset = nCols - nVisCols;
if ( board->xOffset > maxOffset ) { ScrollData* hsd = &board->sd[SCROLL_H];
board->xOffset = maxOffset; 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, if ( figureDims( hsd->dims, VSIZE(hsd->dims), nVisCols,
scale, spares ); scale, spares ) ) {
board_invalAll( board );
}
return scale; return scale;
} /* figureHScale */ } /* figureHScale */
@ -1656,10 +1673,12 @@ figureBoardRect( BoardCtxt* board )
XP_U16 nVisible; XP_U16 nVisible;
XP_U16 nRows = model_numRows( board->model ); XP_U16 nRows = model_numRows( board->model );
XP_U16 boardScale = figureHScale( board ); 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_invalAll( board );
board->boardHScale = boardScale; hsd->scale = boardScale;
} }
/* Figure height of board. Max height is with all rows visible and /* 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; maxHeight = board->trayBounds.top - board->boardBounds.top;
} }
XP_U16 extra; XP_U16 extra;
XP_U16 oldYOffset = vsd->offset;
if ( wantHeight <= maxHeight ) { /* yay! No need to scale */ if ( wantHeight <= maxHeight ) { /* yay! No need to scale */
board->boardVScale = maxHeight / nRows; vsd->scale = maxHeight / nRows;
extra = maxHeight % nRows; extra = maxHeight % nRows;
boardBounds.height = maxHeight; boardBounds.height = maxHeight;
board->boardObscuresTray = XP_FALSE; board->boardObscuresTray = XP_FALSE;
board->yOffset = 0; vsd->offset = 0;
nVisible = nRows; nVisible = nRows;
} else { } else {
XP_S16 maxYOffset; XP_S16 maxYOffset;
XP_U16 oldYOffset = board->yOffset;
XP_Bool yChanged = XP_TRUE; XP_Bool yChanged = XP_TRUE;
/* Need to hide rows etc. */ /* Need to hide rows etc. */
boardBounds.height = maxHeight; boardBounds.height = maxHeight;
board->boardVScale = boardScale; vsd->scale = boardScale;
nVisible = maxHeight / boardScale; nVisible = maxHeight / boardScale;
extra = maxHeight % boardScale; extra = maxHeight % boardScale;
maxYOffset = nRows - nVisible; maxYOffset = nRows - nVisible;
if ( board->yOffset > maxYOffset ) { if ( vsd->offset > maxYOffset ) {
board->yOffset = maxYOffset; vsd->offset = maxYOffset;
} else if ( maxYOffset != board->maxYOffset ) { } else if ( maxYOffset != vsd->maxOffset ) {
board->maxYOffset = maxYOffset; vsd->maxOffset = maxYOffset;
} else { } else {
yChanged = XP_FALSE; yChanged = XP_FALSE;
} }
if ( yChanged ) { board->boardObscuresTray = board->trayBounds.top < wantHeight
util_yOffsetChange( board->util, maxYOffset, oldYOffset, && board->trayBounds.left < (boardBounds.left + boardBounds.width);
board->yOffset );
}
/* XP_LOGF( "%s: maxYOffset: %d; board->yOffset: %d", __func__, */
/* board->maxYOffset, board->yOffset ); */
board->boardObscuresTray = !trayHidden;
} }
board->lastVisibleRow = nVisible + board->yOffset - 1; util_yOffsetChange( board->util, nRows - nVisible, oldYOffset,
vsd->offset );
figureDims( board->rowHeights, VSIZE(board->rowHeights), nVisible, vsd->lastVisible = nVisible + vsd->offset - 1;
board->boardVScale, extra );
if ( figureDims( vsd->dims, VSIZE(vsd->dims), nVisible,
vsd->scale, extra ) ) {
board_invalAll( board );
}
board->boardBounds = boardBounds; 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_U16 maxCols = model_numCols( board->model );
XP_S16 gotCol = -1; XP_S16 gotCol = -1;
XP_S16 gotRow = -1; XP_S16 gotRow = -1;
ScrollData* hsd = &board->sd[SCROLL_H];
ScrollData* vsd = &board->sd[SCROLL_V];
xx -= board->boardBounds.left; xx -= board->boardBounds.left;
XP_ASSERT( xx >= 0 ); XP_ASSERT( xx >= 0 );
for ( col = board->xOffset; col < maxCols; ++col ) { for ( col = hsd->offset; col < maxCols; ++col ) {
xx -= board->colWidths[col]; xx -= hsd->dims[col];
if ( xx < 0 ) { if ( xx < 0 ) {
gotCol = col; gotCol = col;
break; break;
@ -1754,8 +1774,8 @@ coordToCell( BoardCtxt* board, XP_S16 xx, XP_S16 yy, XP_U16* colP,
yy -= board->boardBounds.top; yy -= board->boardBounds.top;
XP_ASSERT( yy >= 0 ); XP_ASSERT( yy >= 0 );
for ( row = board->yOffset; row < maxCols; ++row ) { for ( row = vsd->offset; row < maxCols; ++row ) {
yy -= board->rowHeights[col]; yy -= vsd->dims[col];
if ( yy < 0 ) { if ( yy < 0 ) {
gotRow = row; gotRow = row;
break; break;
@ -1783,20 +1803,22 @@ XP_Bool
getCellRect( const BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Rect* rect ) getCellRect( const BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Rect* rect )
{ {
XP_U16 cur; XP_U16 cur;
XP_Bool onBoard = col >= board->xOffset && row >= board->yOffset const ScrollData* hsd = &board->sd[SCROLL_H];
&& col <= board->lastVisibleCol && row <= board->lastVisibleRow; 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; rect->left = board->boardBounds.left;
for ( cur = board->xOffset; cur < col; ++cur ) { for ( cur = hsd->offset; cur < col; ++cur ) {
rect->left += board->colWidths[cur]; rect->left += hsd->dims[cur];
} }
rect->width = board->colWidths[col]; rect->width = hsd->dims[col];
rect->top = board->boardBounds.top; rect->top = board->boardBounds.top;
for ( cur = board->yOffset; cur < row; ++cur ) { for ( cur = vsd->offset; cur < row; ++cur ) {
rect->top += board->rowHeights[cur]; rect->top += vsd->dims[cur];
} }
rect->height = board->rowHeights[row]; rect->height = vsd->dims[row];
return onBoard; return onBoard;
} /* getCellRect */ } /* getCellRect */
@ -2629,7 +2651,7 @@ invalFocusOwner( BoardCtxt* board )
if ( board->focusHasDived ) { if ( board->focusHasDived ) {
BdCursorLoc loc = pti->bdCursor; BdCursorLoc loc = pti->bdCursor;
invalCell( board, loc.col, loc.row ); invalCell( board, loc.col, loc.row );
checkScrollCell( board, loc.col, loc.row ); scrollIntoView( board, loc.col, loc.row );
} else { } else {
#ifdef PERIMETER_FOCUS #ifdef PERIMETER_FOCUS
invalPerimeter( board ); invalPerimeter( board );
@ -2886,7 +2908,7 @@ board_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool preflightOnly,
loc.col = col; loc.col = col;
loc.row = row; loc.row = row;
pti->bdCursor = loc; pti->bdCursor = loc;
checkScrollCell( board, col, row ); scrollIntoView( board, col, row );
} }
return changed; return changed;
} /* board_moveCursor */ } /* board_moveCursor */
@ -3045,7 +3067,7 @@ setArrowFor( BoardCtxt* board, XP_U16 player, XP_U16 col, XP_U16 row )
arrow->col = (XP_U8)col; arrow->col = (XP_U8)col;
arrow->row = (XP_U8)row; arrow->row = (XP_U8)row;
checkScrollCell( board, col, row ); scrollIntoView( board, col, row );
} /* setArrowFor */ } /* setArrowFor */
static void 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 ); invalCell( (BoardCtxt*)p_board, col, row );

View file

@ -77,7 +77,8 @@ void board_reset( BoardCtxt* board );
XP_Bool board_setYOffset( BoardCtxt* board, XP_U16 newOffset ); XP_Bool board_setYOffset( BoardCtxt* board, XP_U16 newOffset );
XP_U16 board_getYOffset( const BoardCtxt* board ); 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, void board_setScoreboardLoc( BoardCtxt* board,
XP_U16 scoreLeft, XP_U16 scoreTop, XP_U16 scoreLeft, XP_U16 scoreTop,

View file

@ -95,15 +95,16 @@ invalOldPerimeter( BoardCtxt* board )
{ {
/* We need to inval the center of the row that's moving into the center /* 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.) */ 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_U16 firstRow, lastRow;
XP_ASSERT( diff != 0 ); XP_ASSERT( diff != 0 );
if ( diff < 0 ) { if ( diff < 0 ) {
/* moving up; inval row previously on bottom */ /* moving up; inval row previously on bottom */
firstRow = board->yOffset + 1; firstRow = vsd->offset + 1;
lastRow = board->prevYScrollOffset; lastRow = board->prevYScrollOffset;
} else { } else {
XP_U16 nVisible = board->lastVisibleRow - board->yOffset + 1; XP_U16 nVisible = vsd->lastVisible - vsd->offset + 1;
lastRow = board->prevYScrollOffset + nVisible - 1; lastRow = board->prevYScrollOffset + nVisible - 1;
firstRow = lastRow - diff + 1; firstRow = lastRow - diff + 1;
} }
@ -232,9 +233,9 @@ static void
drawBoard( BoardCtxt* board ) drawBoard( BoardCtxt* board )
{ {
if ( board->needsDrawing if ( board->needsDrawing
&& draw_boardBegin( board->draw, && draw_boardBegin( board->draw, &board->boardBounds,
&board->boardBounds, board->sd[SCROLL_H].scale,
board->boardHScale, board->boardVScale, board->sd[SCROLL_V].scale,
dfsFor( board, OBJ_BOARD ) ) ) { dfsFor( board, OBJ_BOARD ) ) ) {
XP_Bool allDrawn = XP_TRUE; XP_Bool allDrawn = XP_TRUE;
@ -242,6 +243,8 @@ drawBoard( BoardCtxt* board )
XP_S16 col, row, nVisCols; XP_S16 col, row, nVisCols;
ModelCtxt* model = board->model; ModelCtxt* model = board->model;
BoardArrow const* arrow = NULL; BoardArrow const* arrow = NULL;
ScrollData* hsd = &board->sd[SCROLL_H];
ScrollData* vsd = &board->sd[SCROLL_V];
BlankQueue bq; BlankQueue bq;
scrollIfCan( board ); /* this must happen before we count blanks scrollIfCan( board ); /* this must happen before we count blanks
@ -270,14 +273,14 @@ drawBoard( BoardCtxt* board )
} }
nVisCols = model_numCols( model ) - board->zoomCount; 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]; XP_U16 rowFlags = board->redrawFlags[row];
if ( rowFlags != 0 ) { if ( rowFlags != 0 ) {
XP_U16 failedBits = 0; XP_U16 failedBits = 0;
for ( col = 0; col < nVisCols; ++col ) { 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 ( 0 != (rowFlags & colMask) ) {
if ( !drawCell( board, col + board->xOffset, if ( !drawCell( board, col + hsd->offset,
row, XP_TRUE )) { row, XP_TRUE )) {
failedBits |= colMask; failedBits |= colMask;
allDrawn = XP_FALSE; allDrawn = XP_FALSE;
@ -451,7 +454,8 @@ static XP_Bool
cellFocused( const BoardCtxt* board, XP_U16 col, XP_U16 row ) cellFocused( const BoardCtxt* board, XP_U16 col, XP_U16 row )
{ {
XP_Bool focussed = XP_FALSE; 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->focussed == OBJ_BOARD) && !board->hideFocus ) {
if ( board->focusHasDived ) { if ( board->focusHasDived ) {
if ( (col == board->selInfo->bdCursor.col) if ( (col == board->selInfo->bdCursor.col)
@ -460,10 +464,10 @@ cellFocused( const BoardCtxt* board, XP_U16 col, XP_U16 row )
} }
} else { } else {
#ifdef PERIMETER_FOCUS #ifdef PERIMETER_FOCUS
focussed = (col == 0) focussed = (col == hsd->offset)
|| (col == model_numCols(board->model) - 1) || (col == hsd->lastVisible)
|| (row == board->yOffset) || (row == vsd->offset)
|| (row == board->lastVisibleRow); || (row == vsd->lastVisible);
#else #else
focussed = XP_TRUE; focussed = XP_TRUE;
#endif #endif
@ -513,6 +517,7 @@ drawDragTileIf( BoardCtxt* board )
static XP_S16 static XP_S16
sumRowHeights( const BoardCtxt* board, XP_U16 row1, XP_U16 row2 ) 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 sign = row1 > row2 ? -1 : 1;
XP_S16 result, ii; XP_S16 result, ii;
if ( sign < 0 ) { if ( sign < 0 ) {
@ -521,7 +526,7 @@ sumRowHeights( const BoardCtxt* board, XP_U16 row1, XP_U16 row2 )
row2 = tmp; row2 = tmp;
} }
for ( result = 0, ii = row1; ii < row2; ++ii ) { for ( result = 0, ii = row1; ii < row2; ++ii ) {
result += board->rowHeights[ii]; result += vsd->dims[ii];
} }
return result * sign; return result * sign;
} }
@ -529,7 +534,8 @@ sumRowHeights( const BoardCtxt* board, XP_U16 row1, XP_U16 row2 )
static void static void
scrollIfCan( BoardCtxt* board ) 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_Rect scrollR = board->boardBounds;
XP_Bool scrolled; XP_Bool scrolled;
XP_S16 dist; XP_S16 dist;
@ -543,7 +549,7 @@ scrollIfCan( BoardCtxt* board )
#endif #endif
invalSelTradeWindow( board ); invalSelTradeWindow( board );
dist = sumRowHeights( board, board->prevYScrollOffset, board->yOffset ); dist = sumRowHeights( board, board->prevYScrollOffset, vsd->offset );
scrolled = draw_vertScrollBoard( board->draw, &scrollR, dist, scrolled = draw_vertScrollBoard( board->draw, &scrollR, dist,
dfsFor( board, OBJ_BOARD ) ); dfsFor( board, OBJ_BOARD ) );
@ -555,7 +561,7 @@ scrollIfCan( BoardCtxt* board )
} else { } else {
board_invalAll( board ); board_invalAll( board );
} }
board->prevYScrollOffset = board->yOffset; board->prevYScrollOffset = vsd->offset;
} }
} /* scrollIfCan */ } /* scrollIfCan */

View file

@ -116,6 +116,14 @@ typedef struct _PerTurnInfo {
#endif #endif
} PerTurnInfo; } 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 { struct BoardCtxt {
/* BoardVTable* vtable; */ /* BoardVTable* vtable; */
@ -125,14 +133,8 @@ struct BoardCtxt {
XW_UtilCtxt* util; XW_UtilCtxt* util;
struct CurGameInfo* gi; 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 preHideYOffset;
XP_U16 prevYScrollOffset; /* represents where the last draw took place; XP_U16 prevYScrollOffset; /* represents where the last draw took place;
used to see if bit scrolling can be used */ used to see if bit scrolling can be used */
@ -171,8 +173,6 @@ struct BoardCtxt {
XP_U16 star_row; XP_U16 star_row;
XP_U16 zoomCount; XP_U16 zoomCount;
XP_U16 colWidths[MAX_COLS];
XP_U16 rowHeights[MAX_COLS];
/* Unless KEYBOARD_NAV is defined, this does not change */ /* Unless KEYBOARD_NAV is defined, this does not change */
BoardObjectType focussed; BoardObjectType focussed;
@ -284,8 +284,9 @@ const XP_UCHAR* getTileDrawInfo( const BoardCtxt* board, Tile tile,
XP_S16* value ); XP_S16* value );
XP_Bool dividerMoved( BoardCtxt* board, XP_U8 newLoc ); XP_Bool dividerMoved( BoardCtxt* board, XP_U8 newLoc );
XP_Bool checkScrollCell( BoardCtxt* board, XP_U16 col, XP_U16 row ); XP_Bool scrollIntoView( BoardCtxt* board, XP_U16 col, XP_U16 row );
XP_Bool onBorderCanScroll( const BoardCtxt* board, XP_U16 row, XP_S16* change ); XP_Bool onBorderCanScroll( const BoardCtxt* board, SDIndex indx, XP_U16 row,
XP_S16* change );
XP_Bool adjustXOffset( BoardCtxt* board, XP_S16 moveBy ); XP_Bool adjustXOffset( BoardCtxt* board, XP_S16 moveBy );
XP_Bool adjustYOffset( BoardCtxt* board, XP_S16 moveBy ); XP_Bool adjustYOffset( BoardCtxt* board, XP_S16 moveBy );

View file

@ -27,7 +27,7 @@ extern "C" {
/* How many squares must scroll gesture take in to be recognized. */ /* How many squares must scroll gesture take in to be recognized. */
#ifndef SCROLL_DRAG_THRESHHOLD #ifndef SCROLL_DRAG_THRESHHOLD
# define SCROLL_DRAG_THRESHHOLD 3 # define SCROLL_DRAG_THRESHHOLD 1
#endif #endif
static XP_Bool dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy, 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 then the alt key determines it. I figure scrolling will be more
common than hint dragging when both are possible, but you can turn 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. */ 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 ) { if ( 0 ) {
#ifdef XWFEATURE_SEARCHLIMIT #ifdef XWFEATURE_SEARCHLIMIT
} else if ( !board->gi->hintsNotAllowed && board->gi->allowHintRect } else if ( !board->gi->hintsNotAllowed && board->gi->allowHintRect
@ -467,13 +468,13 @@ dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy,
#endif #endif
} else if ( ds->dtype == DT_BOARD ) { } else if ( ds->dtype == DT_BOARD ) {
if ( newInfo.obj == OBJ_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; 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; diff /= SCROLL_DRAG_THRESHHOLD;
moving = adjustXOffset( board, diff ) || moving; moving = adjustYOffset( board, diff ) || moving;
} }
} else { } else {
if ( newInfo.obj == OBJ_BOARD ) { if ( newInfo.obj == OBJ_BOARD ) {
@ -572,13 +573,23 @@ scrollTimerProc( void* closure, XWTimerReason XP_UNUSED_DBG(why) )
XP_ASSERT( why == TIMER_PENDOWN ); XP_ASSERT( why == TIMER_PENDOWN );
if ( ds->scrollTimerSet ) { if ( ds->scrollTimerSet ) {
XP_S16 change; XP_S16 changeX = 0;
XP_S16 changeY = 0;
ds->scrollTimerSet = XP_FALSE; 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 ); invalDragObj( board, &ds->cur );
ds->cur.u.board.row += (change >0 ? 1 : -1); if ( 0 != changeX ) {
if ( checkScrollCell( board, ds->cur.u.board.col, ds->cur.u.board.col += (changeX >0 ? 1 : -1);
ds->cur.u.board.row ) ) { }
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 */ board_draw( board ); /* may fail, e.g. on wince */
startScrollTimerIf( board ); startScrollTimerIf( board );
draw = XP_TRUE; draw = XP_TRUE;
@ -595,7 +606,9 @@ startScrollTimerIf( BoardCtxt* board )
if ( (ds->dtype == DT_TILE) && (ds->cur.obj == OBJ_BOARD) ) { if ( (ds->dtype == DT_TILE) && (ds->cur.obj == OBJ_BOARD) ) {
XP_S16 ignore; 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, util_setTimer( board->util, TIMER_PENDOWN, 0,
scrollTimerProc, (void*) board ); scrollTimerProc, (void*) board );
ds->scrollTimerSet = XP_TRUE; ds->scrollTimerSet = XP_TRUE;