Track drag on board to form a rect whose borders are drawn via

attributes on cells; pass that rect to engine when hint requested.
Still rough, and needs to be made per-user.  Also needs a way to hide
the rect.
This commit is contained in:
ehouse 2004-06-15 01:56:01 +00:00
parent 6acff20b42
commit 5cced45556
3 changed files with 249 additions and 8 deletions

View file

@ -94,6 +94,13 @@ static XP_Bool moveKeyTileToBoard( BoardCtxt* board, XP_Key cursorKey );
static XP_Bool moveScoreCursor( BoardCtxt* board, XP_Key key );
static XP_Bool board_moveCursor( BoardCtxt* board, XP_Key cursorKey );
#endif
#ifdef XWFEATURE_SEARCHLIMIT
static HintAtts figureHintAtts( BoardCtxt* board, XP_U16 col, XP_U16 row );
static void invalCurHintRect( BoardCtxt* board, XP_Bool doMirrow );
#else
# define figureHintAtts(b,c,r) HINT_BORDER_NONE
#endif
/*****************************************************************************
*
@ -1332,6 +1339,10 @@ board_flip( BoardCtxt* board )
}
invalCellsWithTiles( board, XP_TRUE );
#ifdef XWFEATURE_SEARCHLIMIT
invalCurHintRect( board, XP_TRUE );
#endif
board->isFlipped = !board->isFlipped;
return board->needsDrawing;
@ -1439,6 +1450,10 @@ board_requestHint( BoardCtxt* board, XP_U16 nTilesToUse, XP_Bool* workRemainsP )
searchComplete = engine_findMove(engine, model,
model_getDictionary(model),
tiles, nTiles, nTilesToUse,
#ifdef XWFEATURE_SEARCHLIMIT
board->hasHintRect?
&board->limits : NULL,
#endif
NO_SCORE_LIMIT,
&canMove, &newMove );
board_popTimerSave( board );
@ -1488,6 +1503,7 @@ drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool skipBlanks )
XP_Bool invert = XP_FALSE;
XP_Bitmap bitmap = NULL;
XP_UCHAR* textP = (XP_UCHAR*)ch;
HintAtts hintAtts;
showPending = board->trayVisState == TRAY_REVEALED;
@ -1519,8 +1535,9 @@ drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool skipBlanks )
}
}
bonus = util_getSquareBonus( board->util, model, col, row );
hintAtts = figureHintAtts( board, col, row );
return draw_drawCell( board->draw, &cellRect, textP, bitmap,
owner, bonus, isBlank, invert,
owner, bonus, hintAtts, isBlank, invert,
(isEmpty && (col==board->star_row)
&& (row==board->star_row)));
}
@ -1751,17 +1768,209 @@ ptOnTradeWindow( BoardCtxt* board, XP_U16 x, XP_U16 y )
return rectContainsPt( windowR, x, y );
} /* ptOnTradeWindow */
#ifdef XWFEATURE_SEARCHLIMIT
static HintAtts
figureHintAtts( BoardCtxt* board, XP_U16 col, XP_U16 row )
{
HintAtts result = HINT_BORDER_NONE;
XP_Bool isFlipped = board->isFlipped;
/* while lets us break to exit... */
while ( board->hasHintRect || board->hintDragInProgress ) {
if ( col < board->limits.left ) break;
if ( row < board->limits.top ) break;
if ( col > board->limits.right ) break;
if ( row > board->limits.bottom ) break;
if ( col == board->limits.left ) {
result |= isFlipped? HINT_BORDER_TOP : HINT_BORDER_LEFT;
}
if ( col == board->limits.right ) {
result |= isFlipped? HINT_BORDER_BOTTOM:HINT_BORDER_RIGHT;
}
if ( row == board->limits.top) {
result |= isFlipped?HINT_BORDER_LEFT:HINT_BORDER_TOP;
}
if ( row == board->limits.bottom ) {
result |= isFlipped? HINT_BORDER_RIGHT:HINT_BORDER_BOTTOM;
}
if ( result == HINT_BORDER_NONE ) {
result = HINT_BORDER_CENTER;
} else {
/* XP_LOGF( "border hints set for {%d,%d}", col, row ); */
}
break;
}
return result;
} /* figureHintAtts */
static XP_Bool
startHintRegionDrag( BoardCtxt* board, XP_U16 x, XP_U16 y )
{
XP_Bool needsRedraw = XP_FALSE;
XP_U16 col, row;
coordToCell( board, x, y, &col, &row );
board->hintDragStartCol = board->hintDragCurCol = col;
board->hintDragStartRow = board->hintDragCurRow = row;
XP_LOGF( "starting drag with %d,%d", col, row );
return needsRedraw;
} /* startHintRegionDrag */
static void
invalCellRegion( BoardCtxt* board, XP_U16 colA, XP_U16 rowA, XP_U16 colB,
XP_U16 rowB, XP_Bool doMirror )
{
XP_U16 col, row, lastCol, firstRow, lastRow;
if ( colA <= colB ) {
col = colA;
lastCol = colB;
} else {
col = colB;
lastCol = colA;
}
if ( rowA <= rowB ) {
row = rowA;
lastRow = rowB;
} else {
row = rowB;
lastRow = rowA;
}
firstRow = row;
for ( ; col <= lastCol; ++col ) {
for( row = firstRow; row <= lastRow; ++row ) {
invalCell( board, col, row, doMirror );
}
}
} /* invalCellRegion */
/* start and end points imply a rect of cells. Changing the end point means
* the borders change and we have to inval all cells whose in-border state is
* changing. Since we also include whether a cell is inside the rect we also
* want to inval for that -- though it won't matter unless somebody manages to
* drag two cols or rows in a single event.
*/
static void
invalHintForNew( BoardCtxt* board, XP_U16 newCol, XP_U16 newRow )
{
invalCellRegion( board, board->hintDragStartCol, board->hintDragStartRow,
newCol, newRow, XP_FALSE );
invalCellRegion( board, board->hintDragCurCol, board->hintDragCurRow,
newCol, newRow, XP_FALSE );
} /* invalHintForNew */
static void
invalCurHintRect( BoardCtxt* board, XP_Bool doMirror )
{
invalCellRegion( board, board->limits.left, board->limits.top,
board->limits.right, board->limits.bottom, doMirror );
} /* invalCurHintRect */
static void
clearCurHintRect( BoardCtxt* board )
{
invalCurHintRect( board, XP_FALSE );
board->hasHintRect = XP_FALSE;
} /* clearCurHintRect */
static void
setHintRect( BoardCtxt* board )
{
if ( board->hintDragStartRow < board->hintDragCurRow ) {
board->limits.top = board->hintDragStartRow;
board->limits.bottom = board->hintDragCurRow;
} else {
board->limits.top = board->hintDragCurRow;
board->limits.bottom = board->hintDragStartRow;
}
if ( board->hintDragStartCol < board->hintDragCurCol ) {
board->limits.left = board->hintDragStartCol;
board->limits.right = board->hintDragCurCol;
} else {
board->limits.left = board->hintDragCurCol;
board->limits.right = board->hintDragStartCol;
}
XP_LOGF( "hintRect now {{%d,%d},{%d,%d}",
board->limits.left, board->limits.top,
board->limits.right, board->limits.bottom );
}
static XP_Bool
continueHintRegionDrag( BoardCtxt* board, XP_U16 x, XP_U16 y )
{
XP_Bool needsRedraw = XP_FALSE;
XP_U16 col, row;
coordToCell( board, x, y, &col, &row );
if ( col != board->hintDragCurCol || row != board->hintDragCurRow ) {
needsRedraw = XP_TRUE;
board->hintDragInProgress = XP_TRUE;
if ( board->hasHintRect ) {
clearCurHintRect( board );
}
/* Now that we've moved, this isn't a timer thing. Clean up any
artifacts. */
board->penTimerFired = XP_FALSE;
if ( valHintMiniWindowActive( board ) ) {
hideMiniWindow( board, XP_TRUE, MINIWINDOW_VALHINT );
}
invalHintForNew( board, col, row );
board->hintDragCurCol = col;
board->hintDragCurRow = row;
setHintRect( board );
XP_LOGF( "now includes with %d,%d", col, row );
}
return needsRedraw;
} /* continueHintRegionDrag */
static XP_Bool
finishHintRegionDrag( BoardCtxt* board, XP_U16 x, XP_U16 y )
{
XP_Bool needsRedraw = XP_FALSE;
XP_ASSERT( board->hintDragInProgress );
needsRedraw = continueHintRegionDrag( board, x, y );
XP_ASSERT( !board->hasHintRect );
board->hasHintRect = XP_TRUE;
XP_LOGF( "done with hint drag. Rect is {{%d,%d},{%d,%d}}",
board->limits.left, board->limits.top,
board->limits.right, board->limits.bottom );
board_resetEngine( board );
return needsRedraw;
} /* finishHintRegionDrag */
#endif
static XP_Bool
handlePenDownOnBoard( BoardCtxt* board, XP_U16 x, XP_U16 y )
{
XP_Bool result;
/* Start a timer no matter what. After it fires we'll decide whether it's
appropriate to handle it. No. That's too expensive */
if ( TRADE_IN_PROGRESS(board) && ptOnTradeWindow( board, x, y ) ) {
return XP_FALSE;
}
util_setTimer( board->util, TIMER_PENDOWN );
#ifdef XWFEATURE_SEARCHLIMIT
result = startHintRegionDrag( board, x, y );
#else
result = XP_FALSE;
#endif
return XP_FALSE;
return result;
} /* handlePenDownOnBoard */
#endif
@ -1888,6 +2097,10 @@ board_handlePenMove( BoardCtxt* board, XP_U16 x, XP_U16 y )
result = continueTileDrag( board, x, y ) != 0;
} else if ( board->divDragState.dragInProgress ) {
result = continueDividerDrag( board, x, y ) != 0;
#ifdef XWFEATURE_SEARCHLIMIT
} else {
result = continueHintRegionDrag( board, x, y );
#endif
}
return result;
@ -2090,7 +2303,12 @@ board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y, XP_Time when )
hideMiniWindow( board, XP_TRUE, MINIWINDOW_VALHINT );
result = XP_TRUE;
}
/* Need to clean up if there's been any dragging happening */
board->penTimerFired = XP_FALSE;
#ifdef XWFEATURE_SEARCHLIMIT
} else if ( board->hintDragInProgress ) {
result = finishHintRegionDrag( board, x, y );
#endif
} else {
BoardObjectType onWhich;
if ( pointOnSomething( board, x, y, &onWhich ) ) {
@ -2129,6 +2347,9 @@ board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y, XP_Time when )
}
}
#ifdef XWFEATURE_SEARCHLIMIT
board->hintDragInProgress = XP_FALSE;
#endif
board->penDownObject = OBJ_NONE;
return result;
} /* board_handlePenUp */

View file

@ -23,6 +23,7 @@
#include "comtypes.h"
#include "model.h"
#include "board.h"
#include "engine.h"
#include "mempool.h" /* debug only */
#ifdef CPLUS
@ -158,6 +159,15 @@ struct BoardCtxt {
XP_Bool showCellValues;
XP_Bool showColors;
#ifdef XWFEATURE_SEARCHLIMIT
XP_U16 hintDragStartCol, hintDragStartRow;
XP_U16 hintDragCurCol, hintDragCurRow;
XP_Bool hintDragInProgress;
XP_Bool hasHintRect;
HintLimits limits;
#endif
MPSLOT
};

View file

@ -37,6 +37,15 @@ typedef struct DrawScoreInfo {
XP_Bool isRobot;
} DrawScoreInfo;
enum HINT_ATTS { HINT_BORDER_NONE = 0,
HINT_BORDER_LEFT = 1,
HINT_BORDER_RIGHT = 2,
HINT_BORDER_TOP = 4,
HINT_BORDER_BOTTOM = 8,
HINT_BORDER_CENTER = 0x10
};
typedef XP_UCHAR HintAtts;
typedef struct DrawCtxVTable {
#ifdef DRAW_WITH_PRIMITIVES
@ -91,10 +100,11 @@ typedef struct DrawCtxVTable {
XP_Bool (*m_draw_drawCell)( DrawCtx* dctx, XP_Rect* rect,
/* at least one of these two will be null */
XP_UCHAR* text, XP_Bitmap bitmap,
XP_S16 owner, /* -1 means don't use */
XWBonusType bonus, XP_Bool isBlank,
XP_Bool highlight, XP_Bool isStar);
XP_UCHAR* text, XP_Bitmap bitmap,
XP_S16 owner, /* -1 means don't use */
XWBonusType bonus, HintAtts hintAtts,
XP_Bool isBlank, XP_Bool highlight,
XP_Bool isStar);
void (*m_draw_invertCell)( DrawCtx* dctx, XP_Rect* rect );
@ -175,9 +185,9 @@ struct DrawCtx {
/* (dc)->vtable->m_draw_frameBoard((dc),(rect)) */
/* #define draw_frameTray( dc, rect ) (dc)->vtable->m_draw_frameTray((dc),(rect)) */
#define draw_drawCell( dc, rect, txt, bmap, o, bon, bl, h, s ) \
#define draw_drawCell( dc, rect, txt, bmap, o, bon, hi, bl, h, s ) \
(dc)->vtable->m_draw_drawCell((dc),(rect),(txt),(bmap),(o),(bon),\
(bl),(h),(s))
(hi),(bl),(h),(s))
#define draw_invertCell( dc, rect ) \
(dc)->vtable->m_draw_invertCell((dc),(rect))