diff --git a/xwords4/wince/ceginfo.c b/xwords4/wince/ceginfo.c index 7505eed51..ef878c117 100755 --- a/xwords4/wince/ceginfo.c +++ b/xwords4/wince/ceginfo.c @@ -51,6 +51,12 @@ typedef struct _GameInfoState { XP_Bool isNewGame; /* newGame or GameInfo */ XP_Bool userCancelled; /* OUT param */ + /* For tracking when to move stuff up/down */ + XP_Bool juggleHidden; + XP_Bool roleConfigHidden; + XP_U16 juggleSpacing; + XP_U16 configSpacing; + GInfoResults results; CePrefsPrefs* prefsPrefs; @@ -286,57 +292,39 @@ stateToGameInfo( GameInfoState* state ) } /* stateToGameInfo */ static void -raiseForHiddenPlayers( GameInfoState* state, XP_U16 nPlayers ) +raiseForJuggle( GameInfoState* state, XP_Bool nowHidden ) { - HWND hDlg = state->dlgHdr.hDlg; - XP_U16 ii; - XP_S16 moveY; - - if ( nPlayers != state->prevNPlayers ) { - if ( !state->moveIds ) { - XP_S16 ids[32]; - HWND child; - RECT rect; - XP_U16 playersBottom; - - ceGetItemRect( hDlg, NAME_EDIT4, &rect ); - playersBottom = rect.bottom; - ceGetItemRect( hDlg, NAME_EDIT3, &rect ); - state->playersSpacing = playersBottom - rect.bottom; - - for ( child = GetWindow( hDlg, GW_CHILD ), ii = 0; - !!child; - child = GetWindow( child, GW_HWNDNEXT ) ) { - XP_S16 resID = GetDlgCtrlID( child ); - if ( resID > 0 ) { - ceGetItemRect( hDlg, resID, &rect ); - if ( rect.top > playersBottom ) { - XP_ASSERT( ii < VSIZE(ids)-1 ); - ids[ii] = resID; - ++ii; - } - } - } - state->moveIds = XP_MALLOC( state->dlgHdr.globals->mpool, - sizeof(state->moveIds[0]) * ii ); - XP_MEMCPY( state->moveIds, ids, sizeof(state->moveIds[0]) * ii ); - state->nMoveIds = ii; - } - - moveY = state->playersSpacing * (nPlayers - state->prevNPlayers); - for ( ii = 0; ii < state->nMoveIds; ++ii ) { - ceMoveItem( hDlg, state->moveIds[ii], 0, moveY ); - } - state->prevNPlayers = nPlayers; - -#ifdef _WIN32_WCE - if ( IS_SMARTPHONE(state->dlgHdr.globals) ) { - SendMessage( hDlg, DM_RESETSCROLL, (WPARAM)FALSE, (LPARAM)TRUE ); - } -#endif + if ( nowHidden != state->juggleHidden ) { + ceDlgMoveBelow( &state->dlgHdr, GIJUGGLE_BUTTON, + state->juggleSpacing * (nowHidden? -1 : 1) ); + state->juggleHidden = nowHidden; } } +#ifndef XWFEATURE_STANDALONE_ONLY +static void +raiseForRoleChange( GameInfoState* state, DeviceRole role ) +{ + XP_Bool configHidden = role == SERVER_STANDALONE; + if ( configHidden != state->roleConfigHidden ) { + ceDlgMoveBelow( &state->dlgHdr, state->roleComboId, + state->configSpacing * (configHidden? -1 : 1) ); + state->roleConfigHidden = configHidden; + } +} +#endif + +static void +raiseForHiddenPlayers( GameInfoState* state, XP_U16 nPlayers ) +{ + if ( nPlayers != state->prevNPlayers ) { + ceDlgMoveBelow( &state->dlgHdr, NAME_EDIT4, + state->playersSpacing + * (nPlayers - state->prevNPlayers) ); + state->prevNPlayers = nPlayers; + } +} /* raiseForHiddenPlayers */ + static void handlePrefsButton( HWND hDlg, CEAppGlobals* globals, GameInfoState* state ) { @@ -378,6 +366,7 @@ handleConnOptionsButton( GameInfoState* state ) GETCURSEL(globals), 0, 0L); value.ng_role = role; newg_attrChanged( state->newGameCtx, NG_ATTR_ROLE, value ); + raiseForRoleChange( state, role ); } /* handleConnOptionsButton */ #endif @@ -462,6 +451,9 @@ ceEnableAttrProc( void* closure, NewGameAttr attr, XP_TriEnable enable ) GameInfoState* state = (GameInfoState*)closure; XP_U16 resID = resIDForAttr( state, attr ); doForNWEnable( state->dlgHdr.hDlg, resID, enable ); + if ( resID == GIJUGGLE_BUTTON ) { + raiseForJuggle( state, enable == TRI_ENAB_HIDDEN ); + } } /* ceEnableAttrProc */ static void @@ -547,6 +539,7 @@ ceSetAttrProc(void* closure, NewGameAttr attr, const NGValue value ) case NG_ATTR_ROLE: SendDlgItemMessage( state->dlgHdr.hDlg, resID, SETCURSEL(globals), value.ng_role, 0L ); + raiseForRoleChange( state, value.ng_role ); break; #endif case NG_ATTR_NPLAYHEADER: @@ -644,7 +637,16 @@ GameInfo( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) state->prevNPlayers = MAX_NUM_PLAYERS; ceDlgSetup( &state->dlgHdr, hDlg, DLG_STATE_TRAPBACK ); + state->playersSpacing = ceDistanceBetween( hDlg, NAME_EDIT3, NAME_EDIT4 ); + state->juggleSpacing = ceDistanceBetween( state->dlgHdr.hDlg, + GIJUGGLE_BUTTON, + IDC_DICTLABEL ); + #ifndef XWFEATURE_STANDALONE_ONLY + state->configSpacing = ceDistanceBetween( state->dlgHdr.hDlg, + IDC_ROLELABEL, + GIROLECONF_BUTTON ); + ceDlgComboShowHide( &state->dlgHdr, IDC_ROLECOMBO ); #endif ceDlgComboShowHide( &state->dlgHdr, IDC_NPLAYERSCOMBO ); @@ -796,9 +798,13 @@ WrapGameInfoDialog( CEAppGlobals* globals, XP_Bool isNewGame, XP_UCHAR* dictName, XP_U16 dictNameLen, GInfoResults* results ) { - GameInfoState state; + GameInfoState state; + XP_U16 resIDs[48]; + XP_MEMSET( &state, 0, sizeof(state) ); state.dlgHdr.globals = globals; + state.dlgHdr.resIDs = resIDs; + state.dlgHdr.nResIDs = VSIZE(resIDs); state.isNewGame = isNewGame; state.prefsPrefs = prefsPrefs; state.newDictName = dictName; diff --git a/xwords4/wince/ceutil.c b/xwords4/wince/ceutil.c index f9f0a401f..c06ea48f7 100755 --- a/xwords4/wince/ceutil.c +++ b/xwords4/wince/ceutil.c @@ -183,6 +183,17 @@ ceMoveItem( HWND hDlg, XP_U16 resID, XP_S16 byX, XP_S16 byY ) } } /* ceMoveItem */ +XP_U16 +ceDistanceBetween( HWND hDlg, XP_U16 resID1, XP_U16 resID2 ) +{ + RECT rect; + ceGetItemRect( hDlg, resID1, &rect ); + XP_U16 top = rect.top; + ceGetItemRect( hDlg, resID2, &rect ); + XP_ASSERT( rect.top > top ); + return rect.top - top; +} + #if 0 /* This has not been tested with ceMoveItem... */ void @@ -360,6 +371,91 @@ ceCenterBy( HWND hDlg, XP_U16 byHowMuch ) } } /* ceCenterBy */ +#define MAX_DLG_ROWS 20 +typedef struct _DlgRow { + XP_U16 top, bottom; + XP_U16 nIds; + XP_U16 ids[12]; +} DlgRow; + +typedef struct _DlgRows { + DlgRow rows[MAX_DLG_ROWS]; + XP_U16 nRows; +} DlgRows; + +static void +insertId( HWND hDlg, DlgRows* rows, XP_U16 id ) +{ + RECT rect; + XP_U16 ii; + DlgRow* row; + ceGetItemRect( hDlg, id, &rect ); + + // Find an entry it fits in, or add a new one. + + for ( ii = 0; ii < MAX_DLG_ROWS; ++ii ) { + row = &rows->rows[ii]; + if ( row->bottom == 0 ) { + row->top = rect.top; + row->bottom = rect.bottom; + ++rows->nRows; + break; + } else if ( rect.top >= row->bottom ) { + /* continue */ + } else if ( rect.bottom <= row->top ) { + /* continue */ + } else { + if ( row->top < rect.top ) { + row->top = rect.top; + } + if ( row->bottom > rect.bottom ) { + row->bottom = rect.bottom; + } + break; + } + } + + XP_ASSERT( ii < VSIZE(rows->rows) ); + + row->ids[row->nIds++] = id; + XP_ASSERT( row->nIds < VSIZE(row->ids) ); +} + +static void +buildIdList( CeDlgHdr* dlgHdr ) +{ + HWND child; + XP_U16 ii, jj; + DlgRows rows; + XP_U16 nResIDsUsed; + + XP_MEMSET( &rows, 0, sizeof(rows) ); + + for ( child = GetWindow( dlgHdr->hDlg, GW_CHILD ), ii = 0; + !!child; + child = GetWindow( child, GW_HWNDNEXT ) ) { + XP_S16 resID = GetDlgCtrlID( child ); + if ( resID > 0 ) { + insertId( dlgHdr->hDlg, &rows, resID ); + } + } + + /* might need to sort first */ + nResIDsUsed = 0; + for ( ii = 0; ii < rows.nRows; ++ii ) { + DlgRow* row = &rows.rows[ii]; + for ( jj = 0; jj < row->nIds; ++jj ) { + XP_U16 id = row->ids[jj]; + dlgHdr->resIDs[nResIDsUsed++] = id; + XP_ASSERT( nResIDsUsed < dlgHdr->nResIDs ); + } + + dlgHdr->resIDs[nResIDsUsed++] = 0; + XP_ASSERT( nResIDsUsed <= dlgHdr->nResIDs ); + } + dlgHdr->nResIDsUsed = nResIDsUsed; +} + #define TITLE_HT 20 /* Need to get this from the OS */ void ceDlgSetup( CeDlgHdr* dlgHdr, HWND hDlg, DlgStateTask doWhat ) @@ -412,6 +508,11 @@ ceDlgSetup( CeDlgHdr* dlgHdr, HWND hDlg, DlgStateTask doWhat ) (void)SetScrollInfo( hDlg, SB_VERT, &sinfo, FALSE ); } + + if ( !!dlgHdr->resIDs ) { + buildIdList( dlgHdr ); + } + dlgHdr->doWhat = doWhat; #ifdef _WIN32_WCE @@ -512,6 +613,45 @@ ceDoDlgHandle( CeDlgHdr* dlgHdr, UINT message, WPARAM wParam, LPARAM lParam ) return handled; } /* ceDoDlgHandle */ +void +ceDlgMoveBelow( CeDlgHdr* dlgHdr, XP_U16 resID, XP_S16 distance ) +{ + XP_U16 ii; + XP_ASSERT( !!dlgHdr->resIDs ); + XP_U16 nResIDsUsed = dlgHdr->nResIDsUsed; + + for ( ii = 0; ii < nResIDsUsed; ++ii ) { + if ( dlgHdr->resIDs[ii] == resID ) { + break; + } + } + + if ( ii < nResIDsUsed ) { /* found it? */ + while ( dlgHdr->resIDs[ii] != 0 ) { /* skip to end of row */ + ++ii; + XP_ASSERT( ii < nResIDsUsed ); /* found it? */ + } + ++ii; /* skip past the 0 */ + + for ( ; ii < nResIDsUsed; ++ii ) { + XP_U16 id = dlgHdr->resIDs[ii]; + if ( 0 != id ) { + ceMoveItem( dlgHdr->hDlg, id, 0, distance ); + } + } + +#ifdef _WIN32_WCE + if ( IS_SMARTPHONE(dlgHdr->globals) ) { + SendMessage( dlgHdr->hDlg, DM_RESETSCROLL, + (WPARAM)FALSE, (LPARAM)TRUE ); + } +#endif + } else { + XP_LOGF( "%s: resID %d not found", __func__, resID ); + } + +} + static void setScrollPos( HWND hDlg, XP_S16 newPos ) { diff --git a/xwords4/wince/ceutil.h b/xwords4/wince/ceutil.h index d05a46067..cf5409b1b 100755 --- a/xwords4/wince/ceutil.h +++ b/xwords4/wince/ceutil.h @@ -51,6 +51,8 @@ int ceMessageBoxChar( CEAppGlobals* globals, const XP_UCHAR* str, XP_Bool isUTF8, const wchar_t* title, XP_U16 buttons ); XP_Bool ceCurDictIsUTF8( CEAppGlobals* globals ); +XP_U16 ceDistanceBetween( HWND hDlg, XP_U16 resID1, XP_U16 resID2 ); + typedef enum { PREFS_FILE_PATH_L ,DEFAULT_DIR_PATH_L @@ -69,17 +71,23 @@ typedef enum { DLG_STATE_NONE = 0 typedef struct CeDlgHdr { CEAppGlobals* globals; HWND hDlg; + /* set these two if will be calling ceDlgMoveBelow */ + XP_U16* resIDs; + XP_U16 nResIDs; /* Below this line is private to ceutil.c */ DlgStateTask doWhat; XP_U16 nPage; XP_U16 prevY; + XP_U16 nResIDsUsed; XP_Bool penDown; } CeDlgHdr; void ceDlgSetup( CeDlgHdr* dlgHdr, HWND hDlg, DlgStateTask doWhat ); void ceDlgComboShowHide( CeDlgHdr* dlgHdr, XP_U16 baseId ); XP_Bool ceDoDlgHandle( CeDlgHdr* dlgHdr, UINT message, WPARAM wParam, LPARAM lParam); +void ceDlgMoveBelow( CeDlgHdr* dlgHdr, XP_U16 resID, XP_S16 distance ); + /* Are we drawing things in landscape mode? */ XP_Bool ceIsLandscape( CEAppGlobals* globals );