void drawScoreBoard( BoardCtxt* board ) { if ( board->scoreBoardInvalid ) { short ii; XP_U16 nPlayers = board->gi->nPlayers; XP_ASSERT( nPlayers <= MAX_NUM_PLAYERS ); if ( nPlayers > 0 ) { ModelCtxt* model = board->model; XP_S16 curTurn = server_getCurrentTurn( board->server ); XP_U16 selPlayer = board->selPlayer; XP_S16 nTilesInPool = server_countTilesInPool( board->server ); XP_Rect scoreRect = board->scoreBdBounds; XP_S16* adjustDim; XP_S16* adjustPt; XP_U16 remWidth, remHeight, remDim; DrawScoreData* dp; DrawScoreData datum[MAX_NUM_PLAYERS]; ScoresArray scores; XP_Bool isVertical = !board->scoreSplitHor; XP_Bool remFocussed = XP_FALSE; XP_Bool focusAll = XP_FALSE; #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 /* Get the scores from the model or by calculating them based on the end-of-game state. */ 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, dfsFor( board, OBJ_SCORE ) ) ) { XP_U16 totalDim = 0; /* not counting rem */ XP_U16 gotPct; /* Let platform decide whether the rem: string should be given any space once there are no tiles left. On Palm that space is clickable to drop a menu, so will probably leave it. */ if ( !draw_measureRemText( board->draw, &board->scoreBdBounds, nTilesInPool, &remWidth, &remHeight ) ) { remWidth = remHeight = 0; } XP_ASSERT( remWidth <= board->scoreBdBounds.width ); XP_ASSERT( remHeight <= board->scoreBdBounds.height ); remDim = isVertical? remHeight : remWidth; if ( isVertical ) { adjustPt = &scoreRect.top; adjustDim = &scoreRect.height; } else { adjustPt = &scoreRect.left; adjustDim = &scoreRect.width; } *adjustDim -= remDim; /* Give as much room as possible to the entry for the player whose turn it is so name can be drawn. Do that by formatting that player's score last, and passing each time the amount of space left. Platform code can then fill that space. */ /* figure spacing for each scoreboard entry */ XP_MEMSET( &datum, 0, sizeof(datum) ); totalDim = 0; for ( dp = datum, ii = 0; ii < nPlayers; ++ii, ++dp ) { LocalPlayer* lp = &board->gi->players[ii]; /* This is a hack! */ dp->dsi.lsc = board_ScoreCallback; dp->dsi.lscClosure = model; #ifdef KEYBOARD_NAV if ( (ii == cursorIndex) || focusAll ) { dp->dsi.flags |= CELL_ISCURSOR; } #endif dp->dsi.playerNum = ii; dp->dsi.totalScore = scores.arr[ii]; dp->dsi.isTurn = (ii == curTurn); dp->dsi.name = emptyStringIfNull(lp->name); dp->dsi.selected = board->trayVisState != TRAY_HIDDEN && ii==selPlayer; dp->dsi.isRobot = LP_IS_ROBOT(lp); dp->dsi.isRemote = !lp->isLocal; dp->dsi.nTilesLeft = (nTilesInPool > 0)? -1: model_getNumTilesTotal( model, ii ); draw_measureScoreText( board->draw, &scoreRect, &dp->dsi, &dp->width, &dp->height ); XP_ASSERT( dp->width <= scoreRect.width ); XP_ASSERT( dp->height <= scoreRect.height ); totalDim += isVertical ? dp->height : dp->width; } gotPct = (*adjustDim * 100) / totalDim; for ( dp = datum, ii = 0; ii < nPlayers; ++ii, ++dp ) { if ( isVertical ) { dp->height = (dp->height * gotPct) / 100; } else { dp->width = (dp->width * gotPct) / 100; } } scoreRect = board->scoreBdBounds; /* reset */ /* at this point, the scoreRect should be anchored at the scoreboard rect's upper left. */ if ( remDim > 0 ) { XP_Rect innerRect; *adjustDim = remDim; centerIn( &innerRect, &scoreRect, remWidth, remHeight ); draw_drawRemText( board->draw, &innerRect, &scoreRect, nTilesInPool, focusAll || remFocussed ); *adjustPt += remDim; #ifdef KEYBOARD_NAV board->remRect = scoreRect; /* Hack: don't let the cursor disappear if Rem: goes away */ } else if ( board->scoreCursorLoc == CURSOR_LOC_REM ) { board->scoreCursorLoc = selPlayer + 1; #endif } board->remDim = remDim; for ( dp = datum, ii = 0; ii < nPlayers; ++dp, ++ii ) { XP_Rect innerRect; XP_U16 dim = isVertical? dp->height:dp->width; *adjustDim = board->pti[ii].scoreDims = dim; centerIn( &innerRect, &scoreRect, dp->width, dp->height ); draw_score_drawPlayer( board->draw, &innerRect, &scoreRect, gotPct, &dp->dsi ); #ifdef KEYBOARD_NAV XP_MEMCPY( &board->pti[ii].scoreRects, &scoreRect, sizeof(scoreRect) ); #endif *adjustPt += *adjustDim; } draw_objFinished( board->draw, OBJ_SCORE, &board->scoreBdBounds, dfsFor( board, OBJ_SCORE ) ); board->scoreBoardInvalid = XP_FALSE; } } } drawTimer( board ); } /* drawScoreBoard */
void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode) { // load styles used by all widgets for(const OTMLNodePtr& node : styleNode->children()) { if(node->tag() == "color") setColor(node->value<Color>()); else if(node->tag() == "x") setX(node->value<int>()); else if(node->tag() == "y") setY(node->value<int>()); else if(node->tag() == "pos") setPosition(node->value<Point>()); else if(node->tag() == "width") setWidth(node->value<int>()); else if(node->tag() == "height") setHeight(node->value<int>()); else if(node->tag() == "rect") setRect(node->value<Rect>()); else if(node->tag() == "background") setBackgroundColor(node->value<Color>()); else if(node->tag() == "background-color") setBackgroundColor(node->value<Color>()); else if(node->tag() == "background-offset-x") setBackgroundOffsetX(node->value<int>()); else if(node->tag() == "background-offset-y") setBackgroundOffsetY(node->value<int>()); else if(node->tag() == "background-offset") setBackgroundOffset(node->value<Point>()); else if(node->tag() == "background-width") setBackgroundWidth(node->value<int>()); else if(node->tag() == "background-height") setBackgroundHeight(node->value<int>()); else if(node->tag() == "background-size") setBackgroundSize(node->value<Size>()); else if(node->tag() == "background-rect") setBackgroundRect(node->value<Rect>()); else if(node->tag() == "icon") setIcon(stdext::resolve_path(node->value(), node->source())); else if(node->tag() == "icon-source") setIcon(stdext::resolve_path(node->value(), node->source())); else if(node->tag() == "icon-color") setIconColor(node->value<Color>()); else if(node->tag() == "icon-offset-x") setIconOffsetX(node->value<int>()); else if(node->tag() == "icon-offset-y") setIconOffsetY(node->value<int>()); else if(node->tag() == "icon-offset") setIconOffset(node->value<Point>()); else if(node->tag() == "icon-width") setIconWidth(node->value<int>()); else if(node->tag() == "icon-height") setIconHeight(node->value<int>()); else if(node->tag() == "icon-size") setIconSize(node->value<Size>()); else if(node->tag() == "icon-rect") setIconRect(node->value<Rect>()); else if(node->tag() == "opacity") setOpacity(node->value<float>()); else if(node->tag() == "enabled") setEnabled(node->value<bool>()); else if(node->tag() == "visible") setVisible(node->value<bool>()); else if(node->tag() == "checked") setChecked(node->value<bool>()); else if(node->tag() == "dragable") setChecked(node->value<bool>()); else if(node->tag() == "on") setOn(node->value<bool>()); else if(node->tag() == "focusable") setFocusable(node->value<bool>()); else if(node->tag() == "phantom") setPhantom(node->value<bool>()); else if(node->tag() == "size") setSize(node->value<Size>()); else if(node->tag() == "fixed-size") setFixedSize(node->value<bool>()); else if(node->tag() == "clipping") setClipping(node->value<bool>()); else if(node->tag() == "border") { auto split = stdext::split(node->value(), " "); if(split.size() == 2) { setBorderWidth(stdext::safe_cast<int>(split[0])); setBorderColor(stdext::safe_cast<Color>(split[1])); } else throw OTMLException(node, "border param must have its width followed by its color"); } else if(node->tag() == "border-width") setBorderWidth(node->value<int>()); else if(node->tag() == "border-width-top") setBorderWidthTop(node->value<int>()); else if(node->tag() == "border-width-right") setBorderWidthRight(node->value<int>()); else if(node->tag() == "border-width-bottom") setBorderWidthBottom(node->value<int>()); else if(node->tag() == "border-width-left") setBorderWidthLeft(node->value<int>()); else if(node->tag() == "border-color") setBorderColor(node->value<Color>()); else if(node->tag() == "border-color-top") setBorderColorTop(node->value<Color>()); else if(node->tag() == "border-color-right") setBorderColorRight(node->value<Color>()); else if(node->tag() == "border-color-bottom") setBorderColorBottom(node->value<Color>()); else if(node->tag() == "border-color-left") setBorderColorLeft(node->value<Color>()); else if(node->tag() == "margin-top") setMarginTop(node->value<int>()); else if(node->tag() == "margin-right") setMarginRight(node->value<int>()); else if(node->tag() == "margin-bottom") setMarginBottom(node->value<int>()); else if(node->tag() == "margin-left") setMarginLeft(node->value<int>()); else if(node->tag() == "margin") { std::string marginDesc = node->value(); std::vector<std::string> split; boost::split(split, marginDesc, boost::is_any_of(std::string(" "))); if(split.size() == 4) { setMarginTop(stdext::safe_cast<int>(split[0])); setMarginRight(stdext::safe_cast<int>(split[1])); setMarginBottom(stdext::safe_cast<int>(split[2])); setMarginLeft(stdext::safe_cast<int>(split[3])); } else if(split.size() == 3) { int marginTop = stdext::safe_cast<int>(split[0]); int marginHorizontal = stdext::safe_cast<int>(split[1]); int marginBottom = stdext::safe_cast<int>(split[2]); setMarginTop(marginTop); setMarginRight(marginHorizontal); setMarginBottom(marginBottom); setMarginLeft(marginHorizontal); } else if(split.size() == 2) { int marginVertical = stdext::safe_cast<int>(split[0]); int marginHorizontal = stdext::safe_cast<int>(split[1]); setMarginTop(marginVertical); setMarginRight(marginHorizontal); setMarginBottom(marginVertical); setMarginLeft(marginHorizontal); } else if(split.size() == 1) { int margin = stdext::safe_cast<int>(split[0]); setMarginTop(margin); setMarginRight(margin); setMarginBottom(margin); setMarginLeft(margin); } } else if(node->tag() == "padding-top") setPaddingTop(node->value<int>()); else if(node->tag() == "padding-right") setPaddingRight(node->value<int>()); else if(node->tag() == "padding-bottom") setPaddingBottom(node->value<int>()); else if(node->tag() == "padding-left") setPaddingLeft(node->value<int>()); else if(node->tag() == "padding") { std::string paddingDesc = node->value(); std::vector<std::string> split; boost::split(split, paddingDesc, boost::is_any_of(std::string(" "))); if(split.size() == 4) { setPaddingTop(stdext::safe_cast<int>(split[0])); setPaddingRight(stdext::safe_cast<int>(split[1])); setPaddingBottom(stdext::safe_cast<int>(split[2])); setPaddingLeft(stdext::safe_cast<int>(split[3])); } else if(split.size() == 3) { int paddingTop = stdext::safe_cast<int>(split[0]); int paddingHorizontal = stdext::safe_cast<int>(split[1]); int paddingBottom = stdext::safe_cast<int>(split[2]); setPaddingTop(paddingTop); setPaddingRight(paddingHorizontal); setPaddingBottom(paddingBottom); setPaddingLeft(paddingHorizontal); } else if(split.size() == 2) { int paddingVertical = stdext::safe_cast<int>(split[0]); int paddingHorizontal = stdext::safe_cast<int>(split[1]); setPaddingTop(paddingVertical); setPaddingRight(paddingHorizontal); setPaddingBottom(paddingVertical); setPaddingLeft(paddingHorizontal); } else if(split.size() == 1) { int padding = stdext::safe_cast<int>(split[0]); setPaddingTop(padding); setPaddingRight(padding); setPaddingBottom(padding); setPaddingLeft(padding); } } // layouts else if(node->tag() == "layout") { std::string layoutType; if(node->hasValue()) layoutType = node->value(); else layoutType = node->valueAt<std::string>("type", ""); if(!layoutType.empty()) { UILayoutPtr layout; if(layoutType == "horizontalBox") layout = UIHorizontalLayoutPtr(new UIHorizontalLayout(asUIWidget())); else if(layoutType == "verticalBox") layout = UIVerticalLayoutPtr(new UIVerticalLayout(asUIWidget())); else if(layoutType == "grid") layout = UIGridLayoutPtr(new UIGridLayout(asUIWidget())); else if(layoutType == "anchor") layout = UIAnchorLayoutPtr(new UIAnchorLayout(asUIWidget())); else throw OTMLException(node, "cannot determine layout type"); setLayout(layout); } if(node->hasChildren()) m_layout->applyStyle(node); } // anchors else if(boost::starts_with(node->tag(), "anchors.")) { UIWidgetPtr parent = getParent(); if(!parent) { if(m_firstOnStyle) throw OTMLException(node, "cannot create anchor, there is no parent widget!"); else continue; } UIAnchorLayoutPtr anchorLayout = parent->getLayout()->asUIAnchorLayout(); if(!anchorLayout) throw OTMLException(node, "cannot create anchor, the parent widget doesn't use anchor layout!"); std::string what = node->tag().substr(8); if(what == "fill") { fill(node->value()); } else if(what == "centerIn") { centerIn(node->value()); } else { Fw::AnchorEdge anchoredEdge = Fw::translateAnchorEdge(what); if(node->value() == "none") { removeAnchor(anchoredEdge); } else { std::vector<std::string> split = stdext::split(node->value(), "."); if(split.size() != 2) throw OTMLException(node, "invalid anchor description"); std::string hookedWidgetId = split[0]; Fw::AnchorEdge hookedEdge = Fw::translateAnchorEdge(split[1]); if(anchoredEdge == Fw::AnchorNone) throw OTMLException(node, "invalid anchor edge"); if(hookedEdge == Fw::AnchorNone) throw OTMLException(node, "invalid anchor target edge"); addAnchor(anchoredEdge, hookedWidgetId, hookedEdge); } } // lua functions } else if(boost::starts_with(node->tag(), "@")) { // load once if(m_firstOnStyle) { std::string funcName = node->tag().substr(1); std::string funcOrigin = "@" + node->source() + "[" + node->tag() + "]"; g_lua.loadFunction(node->value(), funcOrigin); luaSetField(funcName); } // lua fields value } else if(boost::starts_with(node->tag(), "&")) { std::string fieldName = node->tag().substr(1); std::string fieldOrigin = "@" + node->source() + "[" + node->tag() + "]"; g_lua.evaluateExpression(node->value(), fieldOrigin); luaSetField(fieldName); } } }