diff --git a/xwords4/common/draw.h b/xwords4/common/draw.h index 5b71c76a2..bd298af99 100644 --- a/xwords4/common/draw.h +++ b/xwords4/common/draw.h @@ -131,17 +131,26 @@ typedef struct DrawCtxVTable { XP_Bool DRAW_VTABLE_NAME(trayBegin) ( DrawCtx* dctx, const XP_Rect* rect, XP_U16 owner, XP_S16 score, DrawFocusState dfs ); - void DRAW_VTABLE_NAME(measureRemText) ( DrawCtx* dctx, const XP_Rect* r, - XP_S16 nTilesLeft, - XP_U16* width, XP_U16* height ); - void DRAW_VTABLE_NAME(drawRemText) (DrawCtx* dctx, const XP_Rect* rInner, - const XP_Rect* rOuter, - XP_S16 nTilesLeft, XP_Bool focussed ); XP_Bool DRAW_VTABLE_NAME(scoreBegin) ( DrawCtx* dctx, const XP_Rect* rect, XP_U16 numPlayers, const XP_S16* const scores, XP_S16 remCount, DrawFocusState dfs ); +#ifdef XWFEATURE_SCOREONEPASS + void DRAW_VTABLE_NAME(drawRemText) ( DrawCtx* dctx, XP_S16 nTilesLeft, + XP_Bool focussed, XP_Rect* rect ); + void DRAW_VTABLE_NAME(score_drawPlayers)( DrawCtx* dctx, + const XP_Rect* scoreRect, + XP_U16 nPlayers, + DrawScoreInfo playerData[], + XP_Rect playerRects[] ); +#else + void DRAW_VTABLE_NAME(measureRemText) ( DrawCtx* dctx, const XP_Rect* r, + XP_S16 nTilesLeft, + XP_U16* width, XP_U16* height ); + void DRAW_VTABLE_NAME(drawRemText) ( DrawCtx* dctx, const XP_Rect* rInner, + const XP_Rect* rOuter, + XP_S16 nTilesLeft, XP_Bool focussed ); void DRAW_VTABLE_NAME(measureScoreText) ( DrawCtx* dctx, const XP_Rect* r, const DrawScoreInfo* dsi, @@ -151,7 +160,7 @@ typedef struct DrawCtxVTable { const XP_Rect* rOuter, XP_U16 gotPct, const DrawScoreInfo* dsi ); - +#endif void DRAW_VTABLE_NAME(score_pendingScore) ( DrawCtx* dctx, const XP_Rect* rect, XP_S16 score, @@ -271,14 +280,21 @@ struct DrawCtx { CALL_DRAW_NAME3(vertScrollBoard, (dc),(r),(d),(f)) #define draw_scoreBegin( dc, r, t, s, c, f ) \ CALL_DRAW_NAME5( scoreBegin,(dc), (r), (t), (s), (c), (f)) -#define draw_measureRemText( dc, r, n, wp, hp ) \ +#ifdef XWFEATURE_SCOREONEPASS +# define draw_drawRemText( dc, nt, f, ro ) \ + CALL_DRAW_NAME3(drawRemText, (dc), (nt), (f), (ro) ) +# define draw_score_drawPlayers( dc, r, np, pd, pr ) \ + CALL_DRAW_NAME4(score_drawPlayers, (dc), (r), (np), (pd), (pr) ) +#else +# define draw_measureRemText( dc, r, n, wp, hp ) \ CALL_DRAW_NAME4(measureRemText, (dc), (r), (n), (wp), (hp) ) -#define draw_drawRemText( dc, ri, ro, n, f ) \ +# define draw_drawRemText( dc, ri, ro, n, f ) \ CALL_DRAW_NAME4(drawRemText, (dc), (ri), (ro), (n), (f) ) -#define draw_measureScoreText(dc,r,dsi,wp,hp) \ +# define draw_measureScoreText(dc,r,dsi,wp,hp) \ CALL_DRAW_NAME4(measureScoreText,(dc),(r),(dsi),(wp),(hp)) -#define draw_score_drawPlayer(dc, ri, ro, gp, dsi) \ +# define draw_score_drawPlayer(dc, ri, ro, gp, dsi) \ CALL_DRAW_NAME4(score_drawPlayer,(dc),(ri),(ro),(gp),(dsi)) +#endif #define draw_score_pendingScore(dc, r, s, p, f ) \ CALL_DRAW_NAME4(score_pendingScore,(dc), (r), (s), (p), (f)) #define draw_drawTimer( dc, r, plyr, sec ) \ diff --git a/xwords4/common/scorebdp.c b/xwords4/common/scorebdp.c index e74e2e275..f209909db 100644 --- a/xwords4/common/scorebdp.c +++ b/xwords4/common/scorebdp.c @@ -37,6 +37,113 @@ board_ScoreCallback( void* closure, XP_S16 player, XP_UCHAR* expl, expl, explLen ); } /* board_ScoreCallback */ +#ifdef XWFEATURE_SCOREONEPASS +void +drawScoreBoard( BoardCtxt* board ) +{ + if ( board->scoreBoardInvalid ) { + XP_U16 ii; + XP_U16 nPlayers = board->gi->nPlayers; + DrawFocusState dfs = dfsFor( board, OBJ_SCORE ); + ScoresArray scores; + ModelCtxt* model = board->model; + XP_S16 nTilesInPool = server_countTilesInPool( board->server ); + + if ( board->gameOver ) { + model_figureFinalScores( model, &scores, NULL ); + } else { + for ( ii = 0; ii < nPlayers; ++ii ) { + scores.arr[ii] = model_getPlayerScore( model, ii ); + } + } + + if ( draw_scoreBegin( board->draw, &board->scoreBdBounds, nPlayers, + scores.arr, nTilesInPool, dfs ) ) { + XP_S16 curTurn = server_getCurrentTurn( board->server ); + XP_U16 selPlayer = board->selPlayer; + XP_Rect scoreRect; + XP_Rect playerRects[nPlayers]; + XP_U16 remDim; + XP_Bool isVertical = !board->scoreSplitHor; + XP_Bool remFocussed = XP_FALSE; + XP_Bool focusAll = XP_FALSE; + DrawScoreInfo data[nPlayers]; +#ifdef KEYBOARD_NAV + XP_S16 cursorIndex = -1; + + if ( (board->focussed == OBJ_SCORE) && !board->hideFocus ) { + focusAll = !board->focusHasDived; + if ( !focusAll ) { + cursorIndex = board->scoreCursorLoc; + remFocussed = CURSOR_LOC_REM == cursorIndex; + --cursorIndex; + } + } +#endif + + XP_MEMSET( playerRects, 0, sizeof(playerRects) ); + XP_MEMSET( data, 0, sizeof(data) ); + + scoreRect = board->scoreBdBounds; + draw_drawRemText( board->draw, nTilesInPool, focusAll || remFocussed, + &scoreRect ); + XP_ASSERT( rectContainsRect( &board->scoreBdBounds, &scoreRect ) ); + remDim = isVertical? scoreRect.height : scoreRect.width; + board->remDim = remDim; +#ifdef KEYBOARD_NAV + board->remRect = scoreRect; + if ( 0 == remDim && board->scoreCursorLoc == CURSOR_LOC_REM ) { + board->scoreCursorLoc = selPlayer + 1; + } +#endif + scoreRect = board->scoreBdBounds; + if ( isVertical ) { + scoreRect.height -= remDim; + scoreRect.top += remDim; + } else { + scoreRect.width -= remDim; + scoreRect.left += remDim; + } + + for ( ii = 0; ii < nPlayers; ++ii ) { + DrawScoreInfo* dsi = &data[ii]; + LocalPlayer* lp = &board->gi->players[ii]; + dsi->lsc = board_ScoreCallback; + dsi->lscClosure = model; +#ifdef KEYBOARD_NAV + if ( (ii == cursorIndex) || focusAll ) { + dsi->flags |= CELL_ISCURSOR; + } +#endif + dsi->playerNum = ii; + dsi->totalScore = scores.arr[ii]; + dsi->isTurn = (ii == curTurn); + dsi->name = emptyStringIfNull(lp->name); + dsi->selected = board->trayVisState != TRAY_HIDDEN + && ii==selPlayer; + dsi->isRobot = LP_IS_ROBOT(lp); + dsi->isRemote = !lp->isLocal; + dsi->nTilesLeft = (nTilesInPool > 0)? -1: + model_getNumTilesTotal( model, ii ); + } + + draw_score_drawPlayers( board->draw, &scoreRect, nPlayers, data, playerRects ); + for ( ii = 0; ii < nPlayers; ++ii ) { + XP_MEMCPY( &board->pti[ii].scoreRects, &playerRects[ii], + sizeof(board->pti[ii].scoreRects) ); + } + + draw_objFinished( board->draw, OBJ_SCORE, + &board->scoreBdBounds, dfs ); + + board->scoreBoardInvalid = XP_FALSE; + } + } + + drawTimer( board ); +} /* drawScoreBoard */ +#else + static void centerIn( XP_Rect* rInner, const XP_Rect* rOuter, XP_U16 width, XP_U16 height ) { @@ -78,10 +185,7 @@ drawScoreBoard( BoardCtxt* board ) XP_Bool remFocussed = XP_FALSE; XP_Bool focusAll = XP_FALSE; #ifdef KEYBOARD_NAV - XP_Rect cursorRect; - XP_Rect* cursorRectP = NULL; XP_S16 cursorIndex = -1; - if ( (board->focussed == OBJ_SCORE) && !board->hideFocus ) { focusAll = !board->focusHasDived; if ( !focusAll ) { @@ -209,10 +313,6 @@ drawScoreBoard( BoardCtxt* board ) #ifdef KEYBOARD_NAV XP_MEMCPY( &board->pti[ii].scoreRects, &scoreRect, sizeof(scoreRect) ); - if ( ii == cursorIndex ) { - cursorRect = scoreRect; - cursorRectP = &cursorRect; - } #endif *adjustPt += *adjustDim; } @@ -228,6 +328,7 @@ drawScoreBoard( BoardCtxt* board ) drawTimer( board ); } /* drawScoreBoard */ +#endif static XP_S16 figureSecondsLeft( BoardCtxt* board ) diff --git a/xwords4/linux/Makefile b/xwords4/linux/Makefile index 4eaef0f52..b33292566 100644 --- a/xwords4/linux/Makefile +++ b/xwords4/linux/Makefile @@ -95,6 +95,7 @@ DEFINES += -DXWFEATURE_WALKDICT DEFINES += -DXWFEATURE_WALKDICT_FILTER DEFINES += -DXWFEATURE_DICTSANITY DEFINES += -DHASH_STREAM +#DEFINES += -DXWFEATURE_SCOREONEPASS # MAX_ROWS controls STREAM_VERS_BIGBOARD and with it move hashing DEFINES += -DMAX_ROWS=32 diff --git a/xwords4/linux/cursesdraw.c b/xwords4/linux/cursesdraw.c index 2d2e0ab13..db1ae3853 100644 --- a/xwords4/linux/cursesdraw.c +++ b/xwords4/linux/cursesdraw.c @@ -109,6 +109,17 @@ curses_draw_scoreBegin( DrawCtx* p_dctx, const XP_Rect* rect, return XP_TRUE; } /* curses_draw_scoreBegin */ +#ifdef XWFEATURE_SCOREONEPASS +static void +curses_draw_drawRemText( DrawCtx* p_dctx, XP_S16 nTilesLeft, + XP_Bool focussed, XP_Rect* rect ) +{ + XP_USE(p_dctx); + XP_USE(nTilesLeft); + XP_USE(focussed); + XP_USE(rect); +} +#else static void formatRemText( char* buf, int bufLen, XP_S16 nTilesLeft, int width ) { @@ -145,7 +156,10 @@ curses_draw_drawRemText( DrawCtx* p_dctx, const XP_Rect* rInner, cursesHiliteRect( dctx->boardWin, rInner ); } } /* curses_draw_drawRemText */ +#endif +#ifdef XWFEATURE_SCOREONEPASS +#else static int fitIn( char* buf, int len, int* rem, const char* str ) { @@ -243,6 +257,27 @@ curses_draw_measureScoreText( DrawCtx* XP_UNUSED(p_dctx), *height = 1; /* one line per player */ } /* curses_draw_measureScoreText */ +static void +curses_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner, + const XP_Rect* rOuter, + XP_U16 XP_UNUSED(gotPct), const DrawScoreInfo* dsi ) +{ + CursesDrawCtx* dctx = (CursesDrawCtx*)p_dctx; + char buf[100]; + int y = rInner->top; + + curses_draw_clearRect( p_dctx, rOuter ); + + /* print the name and turn/remoteness indicator */ + formatScoreText( buf, sizeof(buf), dsi, rInner->width ); + mvwprintw( dctx->boardWin, y, rOuter->left, buf ); + + if ( (dsi->flags&CELL_ISCURSOR) != 0 ) { + cursesHiliteRect( dctx->boardWin, rOuter ); + } +} /* curses_draw_score_drawPlayer */ +#endif + static void curses_draw_score_pendingScore( DrawCtx* p_dctx, const XP_Rect* rect, XP_S16 score, XP_U16 XP_UNUSED(playerNum), @@ -275,26 +310,6 @@ curses_draw_objFinished( DrawCtx* p_dctx, BoardObjectType XP_UNUSED(typ), #define MY_PAIR 1 -static void -curses_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner, - const XP_Rect* rOuter, - XP_U16 XP_UNUSED(gotPct), const DrawScoreInfo* dsi ) -{ - CursesDrawCtx* dctx = (CursesDrawCtx*)p_dctx; - char buf[100]; - int y = rInner->top; - - curses_draw_clearRect( p_dctx, rOuter ); - - /* print the name and turn/remoteness indicator */ - formatScoreText( buf, sizeof(buf), dsi, rInner->width ); - mvwprintw( dctx->boardWin, y, rOuter->left, buf ); - - if ( (dsi->flags&CELL_ISCURSOR) != 0 ) { - cursesHiliteRect( dctx->boardWin, rOuter ); - } -} /* curses_draw_score_drawPlayer */ - static XP_Bool curses_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* letter, @@ -557,11 +572,15 @@ cursesDrawCtxtMake( WINDOW* boardWin ) SET_VTABLE_ENTRY( dctx->vtable, draw_trayBegin, curses ); SET_VTABLE_ENTRY( dctx->vtable, draw_scoreBegin, curses ); +#ifdef XWFEATURE_SCOREONEPASS + SET_VTABLE_ENTRY( dctx->vtable, draw_drawRemText, curses ); +#else SET_VTABLE_ENTRY( dctx->vtable, draw_measureRemText, curses ); SET_VTABLE_ENTRY( dctx->vtable, draw_drawRemText, curses ); SET_VTABLE_ENTRY( dctx->vtable, draw_measureScoreText, curses ); - SET_VTABLE_ENTRY( dctx->vtable, draw_score_pendingScore, curses ); SET_VTABLE_ENTRY( dctx->vtable, draw_score_drawPlayer, curses ); +#endif + SET_VTABLE_ENTRY( dctx->vtable, draw_score_pendingScore, curses ); SET_VTABLE_ENTRY( dctx->vtable, draw_drawCell, curses ); SET_VTABLE_ENTRY( dctx->vtable, draw_drawTile, curses ); diff --git a/xwords4/linux/gtkdraw.c b/xwords4/linux/gtkdraw.c index b52404de7..7aa0d5548 100644 --- a/xwords4/linux/gtkdraw.c +++ b/xwords4/linux/gtkdraw.c @@ -44,6 +44,10 @@ typedef struct FontPerSize { PangoLayout* layout; } FontPerSize; +static void gtk_draw_measureScoreText( DrawCtx* p_dctx, const XP_Rect* bounds, + const DrawScoreInfo* dsi, + XP_U16* widthP, XP_U16* heightP ); + /* static GdkGC* newGCForColor( GdkWindow* window, XP_Color* newC ); */ static void gtkInsetRect( XP_Rect* r, short i ) @@ -899,6 +903,113 @@ gtkDrawDrawRemText( DrawCtx* p_dctx, const XP_Rect* rect, XP_S16 nTilesLeft, } } /* gtkDrawDrawRemText */ +static void +gtk_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner, + const XP_Rect* rOuter, + XP_U16 XP_UNUSED(gotPct), const DrawScoreInfo* dsi ) +{ + GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx; + XP_Bool hasCursor = (dsi->flags & CELL_ISCURSOR) != 0; + GdkColor* cursor = NULL; + XP_U16 playerNum = dsi->playerNum; + const XP_UCHAR* scoreBuf = dctx->scoreCache[playerNum].str; + XP_U16 fontHt = dctx->scoreCache[playerNum].fontHt; + + if ( hasCursor ) { + cursor = &dctx->cursor; + gtkFillRect( dctx, rOuter, cursor ); + } + +#ifdef USE_CAIRO + //gdk_cairo_set_source_color( dctx->cr, &dctx->playerColors[playerNum] ); +#else + gdk_gc_set_foreground( dctx->drawGC, &dctx->playerColors[playerNum] ); +#endif + + if ( dsi->selected ) { + XP_Rect selRect = *rOuter; + XP_S16 diff; + if ( dctx->scoreIsVertical ) { + diff = selRect.height - rInner->height; + } else { + diff = selRect.width - rInner->width; + } + if ( diff > 0 ) { + if ( dctx->scoreIsVertical ) { + selRect.height -= diff>>1; + selRect.top += diff>>2; + } else { + selRect.width -= diff>>1; + selRect.left += diff>>2; + } + } + + draw_rectangle( dctx, DRAW_WHAT(dctx), dctx->drawGC, + TRUE, selRect.left, selRect.top, + selRect.width, selRect.height ); + if ( hasCursor ) { + gtkFillRect( dctx, rInner, cursor ); + } + gtkEraseRect( dctx, rInner ); + } + +/* XP_U16 fontHt = rInner->height; */ +/* if ( strstr( scoreBuf, "\n" ) ) { */ +/* fontHt >>= 1; */ +/* } */ + + draw_string_at( dctx, NULL, scoreBuf, fontHt/*-1*/, + rInner, XP_GTK_JUST_CENTER, + &dctx->playerColors[playerNum], cursor ); + +} /* gtk_draw_score_drawPlayer */ + +#ifdef XWFEATURE_SCOREONEPASS +static void +gtk_draw_drawRemText( DrawCtx* p_dctx, XP_S16 nTilesLeft, + XP_Bool focussed, XP_Rect* rect ) +{ + if ( nTilesLeft <= 0 ) { + rect->width = rect->height = 0; + } else { + XP_U16 width, height; + gtkDrawDrawRemText( p_dctx, rect, nTilesLeft, &width, &height, focussed ); + rect->width = width; + rect->height = height; + gtkDrawDrawRemText( p_dctx, rect, nTilesLeft, NULL, NULL, focussed ); + } +} + +static void +gtk_draw_score_drawPlayers( DrawCtx* p_dctx, const XP_Rect* scoreRect, + XP_U16 nPlayers, + DrawScoreInfo playerData[], + XP_Rect playerRects[] ) +{ + XP_USE( playerData ); + XP_USE( p_dctx ); + + XP_U16 ii; + XP_Rect rect = *scoreRect; + rect.width /= nPlayers; + for ( ii = 0; ii < nPlayers; ++ii ) { + XP_U16 ignoreW, ignoreH; + XP_Rect innerR; + gtk_draw_measureScoreText( p_dctx, &rect, &playerData[ii], &ignoreW, + &ignoreH ); + + innerR = rect; + innerR.left += 4; + innerR.width -= 8; + gtk_draw_score_drawPlayer( p_dctx, &innerR, &rect, 0, &playerData[ii] ); + + playerRects[ii] = rect; + rect.left += rect.width; + } + +} + +#else static void gtk_draw_measureRemText( DrawCtx* p_dctx, const XP_Rect* rect, XP_S16 nTilesLeft, XP_U16* width, XP_U16* height ) @@ -918,6 +1029,7 @@ gtk_draw_drawRemText( DrawCtx* p_dctx, const XP_Rect* rInner, gtkDrawDrawRemText( p_dctx, rInner, nTilesLeft, NULL, NULL, focussed ); } /* gtk_draw_drawRemText */ +#endif static void formatScoreText( PangoLayout* layout, XP_UCHAR* buf, XP_U16 bufLen, const DrawScoreInfo* dsi, const XP_Rect* bounds, @@ -1011,67 +1123,6 @@ gtk_draw_measureScoreText( DrawCtx* p_dctx, const XP_Rect* bounds, dctx->scoreCache[playerNum].fontHt = lineHeight; } /* gtk_draw_measureScoreText */ -static void -gtk_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner, - const XP_Rect* rOuter, - XP_U16 XP_UNUSED(gotPct), const DrawScoreInfo* dsi ) -{ - GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx; - XP_Bool hasCursor = (dsi->flags & CELL_ISCURSOR) != 0; - GdkColor* cursor = NULL; - XP_U16 playerNum = dsi->playerNum; - const XP_UCHAR* scoreBuf = dctx->scoreCache[playerNum].str; - XP_U16 fontHt = dctx->scoreCache[playerNum].fontHt; - - if ( hasCursor ) { - cursor = &dctx->cursor; - gtkFillRect( dctx, rOuter, cursor ); - } - -#ifdef USE_CAIRO - //gdk_cairo_set_source_color( dctx->cr, &dctx->playerColors[playerNum] ); -#else - gdk_gc_set_foreground( dctx->drawGC, &dctx->playerColors[playerNum] ); -#endif - - if ( dsi->selected ) { - XP_Rect selRect = *rOuter; - XP_S16 diff; - if ( dctx->scoreIsVertical ) { - diff = selRect.height - rInner->height; - } else { - diff = selRect.width - rInner->width; - } - if ( diff > 0 ) { - if ( dctx->scoreIsVertical ) { - selRect.height -= diff>>1; - selRect.top += diff>>2; - } else { - selRect.width -= diff>>1; - selRect.left += diff>>2; - } - } - - draw_rectangle( dctx, DRAW_WHAT(dctx), dctx->drawGC, - TRUE, selRect.left, selRect.top, - selRect.width, selRect.height ); - if ( hasCursor ) { - gtkFillRect( dctx, rInner, cursor ); - } - gtkEraseRect( dctx, rInner ); - } - -/* XP_U16 fontHt = rInner->height; */ -/* if ( strstr( scoreBuf, "\n" ) ) { */ -/* fontHt >>= 1; */ -/* } */ - - draw_string_at( dctx, NULL, scoreBuf, fontHt/*-1*/, - rInner, XP_GTK_JUST_CENTER, - &dctx->playerColors[playerNum], cursor ); - -} /* gtk_draw_score_drawPlayer */ - static void gtk_draw_score_pendingScore( DrawCtx* p_dctx, const XP_Rect* rect, XP_S16 score, XP_U16 XP_UNUSED(playerNum), @@ -1297,10 +1348,15 @@ gtkDrawCtxtMake( GtkWidget* drawing_area, GtkAppGlobals* globals ) SET_VTABLE_ENTRY( dctx->vtable, draw_drawBoardArrow, gtk ); SET_VTABLE_ENTRY( dctx->vtable, draw_scoreBegin, gtk ); +#ifdef XWFEATURE_SCOREONEPASS + SET_VTABLE_ENTRY( dctx->vtable, draw_drawRemText, gtk ); + SET_VTABLE_ENTRY( dctx->vtable, draw_score_drawPlayers, gtk ); +#else SET_VTABLE_ENTRY( dctx->vtable, draw_measureRemText, gtk ); SET_VTABLE_ENTRY( dctx->vtable, draw_drawRemText, gtk ); SET_VTABLE_ENTRY( dctx->vtable, draw_measureScoreText, gtk ); SET_VTABLE_ENTRY( dctx->vtable, draw_score_drawPlayer, gtk ); +#endif SET_VTABLE_ENTRY( dctx->vtable, draw_score_pendingScore, gtk ); SET_VTABLE_ENTRY( dctx->vtable, draw_drawTimer, gtk );