mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-06 20:45:54 +01:00
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:
parent
7efcdc80fe
commit
da4fe889f1
3 changed files with 249 additions and 8 deletions
|
@ -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 moveScoreCursor( BoardCtxt* board, XP_Key key );
|
||||||
static XP_Bool board_moveCursor( BoardCtxt* board, XP_Key cursorKey );
|
static XP_Bool board_moveCursor( BoardCtxt* board, XP_Key cursorKey );
|
||||||
#endif
|
#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 );
|
invalCellsWithTiles( board, XP_TRUE );
|
||||||
|
|
||||||
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
|
invalCurHintRect( board, XP_TRUE );
|
||||||
|
#endif
|
||||||
|
|
||||||
board->isFlipped = !board->isFlipped;
|
board->isFlipped = !board->isFlipped;
|
||||||
|
|
||||||
return board->needsDrawing;
|
return board->needsDrawing;
|
||||||
|
@ -1439,6 +1450,10 @@ board_requestHint( BoardCtxt* board, XP_U16 nTilesToUse, XP_Bool* workRemainsP )
|
||||||
searchComplete = engine_findMove(engine, model,
|
searchComplete = engine_findMove(engine, model,
|
||||||
model_getDictionary(model),
|
model_getDictionary(model),
|
||||||
tiles, nTiles, nTilesToUse,
|
tiles, nTiles, nTilesToUse,
|
||||||
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
|
board->hasHintRect?
|
||||||
|
&board->limits : NULL,
|
||||||
|
#endif
|
||||||
NO_SCORE_LIMIT,
|
NO_SCORE_LIMIT,
|
||||||
&canMove, &newMove );
|
&canMove, &newMove );
|
||||||
board_popTimerSave( board );
|
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_Bool invert = XP_FALSE;
|
||||||
XP_Bitmap bitmap = NULL;
|
XP_Bitmap bitmap = NULL;
|
||||||
XP_UCHAR* textP = (XP_UCHAR*)ch;
|
XP_UCHAR* textP = (XP_UCHAR*)ch;
|
||||||
|
HintAtts hintAtts;
|
||||||
|
|
||||||
showPending = board->trayVisState == TRAY_REVEALED;
|
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 );
|
bonus = util_getSquareBonus( board->util, model, col, row );
|
||||||
|
hintAtts = figureHintAtts( board, col, row );
|
||||||
return draw_drawCell( board->draw, &cellRect, textP, bitmap,
|
return draw_drawCell( board->draw, &cellRect, textP, bitmap,
|
||||||
owner, bonus, isBlank, invert,
|
owner, bonus, hintAtts, isBlank, invert,
|
||||||
(isEmpty && (col==board->star_row)
|
(isEmpty && (col==board->star_row)
|
||||||
&& (row==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 );
|
return rectContainsPt( windowR, x, y );
|
||||||
} /* ptOnTradeWindow */
|
} /* 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
|
static XP_Bool
|
||||||
handlePenDownOnBoard( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
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
|
/* Start a timer no matter what. After it fires we'll decide whether it's
|
||||||
appropriate to handle it. No. That's too expensive */
|
appropriate to handle it. No. That's too expensive */
|
||||||
if ( TRADE_IN_PROGRESS(board) && ptOnTradeWindow( board, x, y ) ) {
|
if ( TRADE_IN_PROGRESS(board) && ptOnTradeWindow( board, x, y ) ) {
|
||||||
return XP_FALSE;
|
return XP_FALSE;
|
||||||
}
|
}
|
||||||
util_setTimer( board->util, TIMER_PENDOWN );
|
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 */
|
} /* handlePenDownOnBoard */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1888,6 +2097,10 @@ board_handlePenMove( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
||||||
result = continueTileDrag( board, x, y ) != 0;
|
result = continueTileDrag( board, x, y ) != 0;
|
||||||
} else if ( board->divDragState.dragInProgress ) {
|
} else if ( board->divDragState.dragInProgress ) {
|
||||||
result = continueDividerDrag( board, x, y ) != 0;
|
result = continueDividerDrag( board, x, y ) != 0;
|
||||||
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
|
} else {
|
||||||
|
result = continueHintRegionDrag( board, x, y );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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 );
|
hideMiniWindow( board, XP_TRUE, MINIWINDOW_VALHINT );
|
||||||
result = XP_TRUE;
|
result = XP_TRUE;
|
||||||
}
|
}
|
||||||
|
/* Need to clean up if there's been any dragging happening */
|
||||||
board->penTimerFired = XP_FALSE;
|
board->penTimerFired = XP_FALSE;
|
||||||
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
|
} else if ( board->hintDragInProgress ) {
|
||||||
|
result = finishHintRegionDrag( board, x, y );
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
BoardObjectType onWhich;
|
BoardObjectType onWhich;
|
||||||
if ( pointOnSomething( board, x, y, &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;
|
board->penDownObject = OBJ_NONE;
|
||||||
return result;
|
return result;
|
||||||
} /* board_handlePenUp */
|
} /* board_handlePenUp */
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "comtypes.h"
|
#include "comtypes.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
#include "engine.h"
|
||||||
#include "mempool.h" /* debug only */
|
#include "mempool.h" /* debug only */
|
||||||
|
|
||||||
#ifdef CPLUS
|
#ifdef CPLUS
|
||||||
|
@ -158,6 +159,15 @@ struct BoardCtxt {
|
||||||
XP_Bool showCellValues;
|
XP_Bool showCellValues;
|
||||||
XP_Bool showColors;
|
XP_Bool showColors;
|
||||||
|
|
||||||
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
|
XP_U16 hintDragStartCol, hintDragStartRow;
|
||||||
|
XP_U16 hintDragCurCol, hintDragCurRow;
|
||||||
|
XP_Bool hintDragInProgress;
|
||||||
|
|
||||||
|
XP_Bool hasHintRect;
|
||||||
|
HintLimits limits;
|
||||||
|
#endif
|
||||||
|
|
||||||
MPSLOT
|
MPSLOT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,15 @@ typedef struct DrawScoreInfo {
|
||||||
XP_Bool isRobot;
|
XP_Bool isRobot;
|
||||||
} DrawScoreInfo;
|
} 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 {
|
typedef struct DrawCtxVTable {
|
||||||
|
|
||||||
#ifdef DRAW_WITH_PRIMITIVES
|
#ifdef DRAW_WITH_PRIMITIVES
|
||||||
|
@ -91,10 +100,11 @@ typedef struct DrawCtxVTable {
|
||||||
|
|
||||||
XP_Bool (*m_draw_drawCell)( DrawCtx* dctx, XP_Rect* rect,
|
XP_Bool (*m_draw_drawCell)( DrawCtx* dctx, XP_Rect* rect,
|
||||||
/* at least one of these two will be null */
|
/* at least one of these two will be null */
|
||||||
XP_UCHAR* text, XP_Bitmap bitmap,
|
XP_UCHAR* text, XP_Bitmap bitmap,
|
||||||
XP_S16 owner, /* -1 means don't use */
|
XP_S16 owner, /* -1 means don't use */
|
||||||
XWBonusType bonus, XP_Bool isBlank,
|
XWBonusType bonus, HintAtts hintAtts,
|
||||||
XP_Bool highlight, XP_Bool isStar);
|
XP_Bool isBlank, XP_Bool highlight,
|
||||||
|
XP_Bool isStar);
|
||||||
|
|
||||||
void (*m_draw_invertCell)( DrawCtx* dctx, XP_Rect* rect );
|
void (*m_draw_invertCell)( DrawCtx* dctx, XP_Rect* rect );
|
||||||
|
|
||||||
|
@ -175,9 +185,9 @@ struct DrawCtx {
|
||||||
/* (dc)->vtable->m_draw_frameBoard((dc),(rect)) */
|
/* (dc)->vtable->m_draw_frameBoard((dc),(rect)) */
|
||||||
/* #define draw_frameTray( dc, rect ) (dc)->vtable->m_draw_frameTray((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),\
|
(dc)->vtable->m_draw_drawCell((dc),(rect),(txt),(bmap),(o),(bon),\
|
||||||
(bl),(h),(s))
|
(hi),(bl),(h),(s))
|
||||||
|
|
||||||
#define draw_invertCell( dc, rect ) \
|
#define draw_invertCell( dc, rect ) \
|
||||||
(dc)->vtable->m_draw_invertCell((dc),(rect))
|
(dc)->vtable->m_draw_invertCell((dc),(rect))
|
||||||
|
|
Loading…
Add table
Reference in a new issue