Index: binaries/data/mods/public/gui/civinfo/civinfo.js =================================================================== --- binaries/data/mods/public/gui/civinfo/civinfo.js +++ binaries/data/mods/public/gui/civinfo/civinfo.js @@ -84,12 +84,12 @@ { if (!obj.Name) return ""; - let string = '[font="sans-bold-14"]' + obj.Name + '[/font] '; + let string = setStringTags(obj.Name, { "font": "sans-bold-14" }); if (obj.History) string += '[icon="iconInfo" tooltip="' + escapeQuotation(obj.History) + '" tooltip_style="civInfoTooltip"]'; if (obj.Description) string += '\n ' + obj.Description; - return coloredText(string + "\n", "white"); + return setStringTags(string + "\n", { "color": "white" }); } function switchToStrucTreePage() Index: binaries/data/mods/public/gui/common/color.js =================================================================== --- binaries/data/mods/public/gui/common/color.js +++ binaries/data/mods/public/gui/common/color.js @@ -187,5 +187,5 @@ */ function compatibilityColor(text, isCompatible) { - return isCompatible ? text : coloredText(text, "96 96 96"); + return isCompatible ? text : setStringTags(text, { "color": "96 96 96" }); } Index: binaries/data/mods/public/gui/common/functions_global_object.js =================================================================== --- binaries/data/mods/public/gui/common/functions_global_object.js +++ binaries/data/mods/public/gui/common/functions_global_object.js @@ -75,7 +75,7 @@ Engine.PushGuiPage("page_msgbox.xml", { "width": 500, "height": 200, - "message": '[font="sans-bold-18"]' + msg + '[/font]', + "message": setStringTags(msg, { "font": "sans-bold-18" }), "title": translate("Loading Aborted"), "mode": 2 }); Index: binaries/data/mods/public/gui/common/gamedescription.js =================================================================== --- binaries/data/mods/public/gui/common/gamedescription.js +++ binaries/data/mods/public/gui/common/gamedescription.js @@ -1,7 +1,12 @@ /** * Highlights the victory condition in the game-description. */ -var g_DescriptionHighlight = "orange"; +var g_DescriptionHighlight = { "color": "orange" }; + +/** + * Font of the teams. + */ +var g_TeamDescriptionCaptionTag = { "font": "sans-bold-14" }; /** * The rating assigned to lobby players who didn't complete a ranked 1v1 yet. @@ -169,12 +174,13 @@ let playerNick = splitRatingFromNick(playerData.Name).nick; playerDescriptions[teamIdx].push(sprintf(playerDescription, { "playerName": - coloredText( + setStringTags( (g_Buddies.indexOf(playerNick) != -1 ? g_BuddySymbol + " " : "") + escapeText(playerData.Name), - (typeof getPlayerColor == 'function' ? + { "color": (typeof getPlayerColor == 'function' ? (isAI ? "white" : getPlayerColor(playerNick)) : - rgbToGuiColor(playerData.Color || g_Settings.PlayerDefaults[playerIdx].Color))), + rgbToGuiColor(playerData.Color || g_Settings.PlayerDefaults[playerIdx].Color)) } + ), "civ": !playerData.Civ ? @@ -212,14 +218,14 @@ // Translation: Describe players of one team in a selected game, f.e. in the replay- or savegame menu or lobby return sprintf(translate("%(team)s:\n%(playerDescriptions)s"), { - "team": '[font="sans-bold-14"]' + teamCaption + "[/font]", + "team": setStringTags(teamCaption, g_TeamDescriptionCaptionTag), "playerDescriptions": playerDescriptions[team].join("\n") }); }); if (playerDescriptions.observer) teamDescription.push(sprintf(translate("%(team)s:\n%(playerDescriptions)s"), { - "team": '[font="sans-bold-14"]' + translatePlural("Observer", "Observers", playerDescriptions.observer.length) + "[/font]", + "team": setStringTags(translatePlural("Observer", "Observers", playerDescriptions.observer.length), g_TeamDescriptionCaptionTag), "playerDescriptions": playerDescriptions.observer.join("\n") })); @@ -442,7 +448,7 @@ }); return titles.map(title => sprintf(translate("%(label)s %(details)s"), { - "label": coloredText(title.label, g_DescriptionHighlight), + "label": setStringTags(title.label, g_DescriptionHighlight), "details": title.value === true ? translateWithContext("gamesetup option", "enabled") : title.value || translateWithContext("gamesetup option", "disabled") Index: binaries/data/mods/public/gui/common/tooltips.js =================================================================== --- binaries/data/mods/public/gui/common/tooltips.js +++ binaries/data/mods/public/gui/common/tooltips.js @@ -5,7 +5,9 @@ "comma": { "font": "sans-12" }, "nameSpecificBig": { "font": "sans-bold-16" }, "nameSpecificSmall": { "font": "sans-bold-12" }, - "nameGeneric": { "font": "sans-bold-16" } + "nameGeneric": { "font": "sans-bold-16" }, + "insufficient": { "font": "sans-bold-13", "color": "red" }, + "armour": { "font": "sans-10" } }; var g_AttackTypes = { @@ -221,11 +223,9 @@ dmgType => sprintf(translate("%(damage)s %(damageType)s %(armorPercentage)s"), { "damage": template.armour[dmgType].toFixed(1), "damageType": unitFont(translateWithContext("damage type", dmgType)), - "armorPercentage": - '[font="sans-10"]' + - sprintf(translate("(%(armorPercentage)s)"), { - "armorPercentage": armorLevelToPercentageString(template.armour[dmgType]) - }) + '[/font]' + "armorPercentage": setStringTags(sprintf(translate("(%(armorPercentage)s)"), { + "armorPercentage": armorLevelToPercentageString(template.armour[dmgType]) + }), g_TooltipTextFormats.armour) }) ).join(commaFont(translate(", "))) }); @@ -234,7 +234,7 @@ function damageTypesToText(dmg) { if (!dmg) - return '[font="sans-12"]' + translate("(None)") + '[/font]'; + return setStringTags(translate("(None)"), { "font": "sans-12" }); return Object.keys(dmg).filter(dmgType => dmg[dmgType]).map( dmgType => sprintf(translate("%(damage)s %(damageType)s"), { @@ -651,12 +651,10 @@ let formatted = []; for (let resource in resources) formatted.push(sprintf(translate("%(component)s %(cost)s"), { - "component": '[font="sans-12"]' + resourceIcon(resource) + '[/font]', + "component": resourceIcon(resource), "cost": resources[resource] })); - return coloredText( - '[font="sans-bold-13"]' + translate("Insufficient resources:") + '[/font]', - "red") + " " + + return setStringTags(translate("Insufficient resources:"), g_TooltipTextFormats.insufficient) + " " + formatted.join(" "); } @@ -762,13 +760,11 @@ return setStringTags(template.name.generic, g_TooltipTextFormats.nameSpecificBig); // Translation: Example: "Epibátēs Athēnaîos [font="sans-bold-16"](Athenian Marine)[/font]" - return sprintf(translate("%(specificName)s %(fontStart)s(%(genericName)s)%(fontEnd)s"), { + return sprintf(translate("%(specificName)s (%(genericName)s)"), { "specificName": setStringTags(template.name.specific[0], g_TooltipTextFormats.nameSpecificBig) + setStringTags(template.name.specific.slice(1).toUpperCase(), g_TooltipTextFormats.nameSpecificSmall), - "genericName": template.name.generic, - "fontStart": '[font="' + g_TooltipTextFormats.nameGeneric.font + '"]', - "fontEnd": '[/font]' + "genericName": setStringTags(template.name.generic, g_TooltipTextFormats.nameGeneric) }); } Index: binaries/data/mods/public/gui/gamesetup/gamesetup.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/gamesetup.js +++ binaries/data/mods/public/gui/gamesetup/gamesetup.js @@ -49,7 +49,7 @@ /** * Used for highlighting the sender of chat messages. */ -var g_SenderFont = "sans-bold-13"; +var g_SenderFontTag = { "font": "sans-bold-13" }; /** * This yields [1, 2, ..., MaxPlayers]. @@ -588,12 +588,12 @@ if (hoverIdx == -1 || popCap * players <= g_PopulationCapacityRecommendation) return translate("Select population limit."); - return coloredText( + return setStringTags( sprintf(translate("Warning: There might be performance issues if all %(players)s players reach %(popCap)s population."), { "players": players, "popCap": popCap }), - "orange"); + { "color": "orange" }); }, "labels": () => g_PopulationCapacities.Title, "ids": () => g_PopulationCapacities.Population, @@ -1094,7 +1094,7 @@ let name = translate(pData.Name || g_DefaultPlayerData[playerIdx].Name); if (g_IsNetworked) - name = coloredText(name, g_ReadyData[assignedGUID ? g_PlayerAssignments[assignedGUID].status : 2].color); + name = setStringTags(name, { "color": g_ReadyData[assignedGUID ? g_PlayerAssignments[assignedGUID].status : 2].color }); return name; }, @@ -1345,7 +1345,7 @@ dropdown.list = data.labels(playerIdx).map((label, id) => data.colors && data.colors(playerIdx) ? - coloredText(label, data.colors(playerIdx)[id]) : + setStringTags(label, { "color": data.colors(playerIdx)[id] }) : label); dropdown.list_data = data.ids(playerIdx); @@ -2538,7 +2538,7 @@ function senderFont(text) { - return '[font="' + g_SenderFont + '"]' + text + '[/font]'; + return setStringTags(text, g_SenderFontTag); } function systemMessage(message) @@ -2565,7 +2565,7 @@ color = rgbToGuiColor({ "r": r, "g": g, "b": b }); } - return coloredText(username, color); + return setStringTags(username, { "color": color }); } function addChatMessage(msg) Index: binaries/data/mods/public/gui/loadgame/load.js =================================================================== --- binaries/data/mods/public/gui/loadgame/load.js +++ binaries/data/mods/public/gui/loadgame/load.js @@ -117,7 +117,7 @@ let caption = sprintf(translate("Mods: %(mods)s"), { "mods": modsToString(metadata.mods) }); if (!hasSameMods(metadata.mods, Engine.GetEngineInfo().mods)) - caption = coloredText(caption, "orange"); + caption = setStringTags(caption, { "color": "orange" }); Engine.GetGUIObjectByName("savedMods").caption = caption; Engine.GetGUIObjectByName("savedPlayersNames").caption = formatPlayerInfo( Index: binaries/data/mods/public/gui/lobby/lobby.js =================================================================== --- binaries/data/mods/public/gui/lobby/lobby.js +++ binaries/data/mods/public/gui/lobby/lobby.js @@ -68,17 +68,17 @@ /** * Color for private messages in the chat. */ -var g_PrivateMessageColor = "0 150 0"; +var g_PrivateMessageTag = { "color": "0 150 0" }; /** * Used for highlighting the sender of chat messages. */ -var g_SenderFont = "sans-bold-13"; +var g_SenderFontTag = { "font": "sans-bold-13" }; /** * Color to highlight chat commands in the explanation. */ -var g_ChatCommandColor = "200 200 255"; +var g_ChatCommandTag = { "color": "200 200 255" }; /** * Indicates if the lobby is opened as a dialog or window. @@ -355,7 +355,7 @@ if (!g_ChatCommands[command].moderatorOnly || isModerator) // Translation: Chat command help format text += "\n" + sprintf(translate("%(command)s - %(description)s"), { - "command": coloredText(command, g_ChatCommandColor), + "command": setStringTags(command, g_ChatCommandTag), "description": g_ChatCommands[command].description }); @@ -748,11 +748,11 @@ if (presence == "unknown") warn("Unknown presence:" + player.presence); - let statusColor = g_PlayerStatuses[presence].color; - buddyStatusList.push(player.isBuddy ? coloredText(g_BuddySymbol, statusColor) : ""); + let statusColor = { "color": g_PlayerStatuses[presence].color }; + buddyStatusList.push(player.isBuddy ? setStringTags(g_BuddySymbol, statusColor) : ""); playerList.push(colorPlayerName((player.role == "moderator" ? g_ModeratorPrefix : "") + player.name)); - presenceList.push(coloredText(g_PlayerStatuses[presence].status, statusColor)); - ratingList.push(coloredText(rating, statusColor)); + presenceList.push(setStringTags(g_PlayerStatuses[presence].status, statusColor)); + ratingList.push(setStringTags(rating, statusColor)); nickList.push(player.name); } @@ -1082,8 +1082,8 @@ if (game.ip == g_SelectedGameIP && game.port == g_SelectedGamePort) selectedGameIndex = +i; - list_buddy.push(game.hasBuddies ? coloredText(g_BuddySymbol, g_GameColors[game.state]) : ""); - list_name.push(coloredText(gameName, g_GameColors[game.state])); + list_buddy.push(game.hasBuddies ? setStringTags(g_BuddySymbol, { "color": g_GameColors[game.state] }) : ""); + list_name.push(setStringTags(gameName, { "color": g_GameColors[game.state] })); list_mapName.push(translateMapTitle(game.niceMapName)); list_mapSize.push(translateMapSize(game.mapSize)); list_mapType.push(g_MapTypes.Title[mapTypeIdx] || ""); @@ -1357,7 +1357,7 @@ "from": "system", "text": sprintf( translate("The command '%(cmd)s' is not supported."), { - "cmd": coloredText(cmd, g_ChatCommandColor) + "cmd": setStringTags(cmd, g_ChatCommandTag) }) }); return false; @@ -1369,7 +1369,7 @@ "from": "system", "text": sprintf( translate("The command '%(cmd)s' is restricted to moderators."), { - "cmd": coloredText(cmd, g_ChatCommandColor) + "cmd": setStringTags(cmd, g_ChatCommandTag) }) }); return false; @@ -1499,7 +1499,7 @@ // Translation: IRC message prefix. if (msg.private) senderString = sprintf(translateWithContext("lobby private message", "(%(private)s) <%(sender)s>"), { - "private": coloredText(translate("Private"), g_PrivateMessageColor), + "private": setStringTags(translate("Private"), g_PrivateMessageTag), "sender": coloredFrom }); else @@ -1566,19 +1566,19 @@ */ function colorPlayerName(playername, rating) { - return coloredText( + return setStringTags( (rating ? sprintf( translate("%(nick)s (%(rating)s)"), { "nick": playername, "rating": rating }) : playername ), - getPlayerColor(playername.replace(g_ModeratorPrefix, ""))); + { "color": getPlayerColor(playername.replace(g_ModeratorPrefix, "")) }); } function senderFont(text) { - return '[font="' + g_SenderFont + '"]' + text + "[/font]"; + return setStringTag(text, g_SenderFontTag); } function formatWinRate(attr) Index: binaries/data/mods/public/gui/pregame/mainmenu.js =================================================================== --- binaries/data/mods/public/gui/pregame/mainmenu.js +++ binaries/data/mods/public/gui/pregame/mainmenu.js @@ -111,7 +111,7 @@ 600, 300, "[font=\"sans-bold-16\"]" + sprintf(translate("%(warning)s You appear to be using non-shader (fixed function) graphics. This option will be removed in a future 0 A.D. release, to allow for more advanced graphics features. We advise upgrading your graphics card to a more recent, shader-compatible model."), { - "warning": coloredText("Warning:", "200 20 20") + "warning": setStringTags("Warning:", { "color": "200 20 20" }) }) + "\n\n" + // Translation: This is the second paragraph of a warning. The Index: binaries/data/mods/public/gui/session/menu.js =================================================================== --- binaries/data/mods/public/gui/session/menu.js +++ binaries/data/mods/public/gui/session/menu.js @@ -23,7 +23,7 @@ var STEP = 5; // Shown in the trade dialog. -var g_IdleTraderTextColor = "orange"; +var g_IdleTraderTextTag = { "color": "orange" }; /** * Store civilization code and page (structree or history) opened in civilization info. @@ -944,7 +944,7 @@ "openingTradingString": activeString, "openingGarrisonedString": garrisonedString, "garrisonedString": garrisonedString, - "inactiveString": coloredText(inactiveString, g_IdleTraderTextColor) + "inactiveString": setStringTags(inactiveString, g_IdleTraderTextTag) }); } @@ -992,7 +992,7 @@ return sprintf(message, { "openingTradingString": activeString, - "inactiveString": coloredText(inactiveString, g_IdleTraderTextColor) + "inactiveString": setStringTags(inactiveString, g_IdleTraderTextTag) }); } Index: binaries/data/mods/public/gui/session/messages.js =================================================================== --- binaries/data/mods/public/gui/session/messages.js +++ binaries/data/mods/public/gui/session/messages.js @@ -567,7 +567,7 @@ if (notification.warning) { - Engine.GetGUIObjectByName("tutorialWarning").caption = coloredText(translate(notification.warning), "orange"); + Engine.GetGUIObjectByName("tutorialWarning").caption = setStringTags(translate(notification.warning), { "color": "orange" }); return; } @@ -971,7 +971,7 @@ function colorizePlayernameHelper(username, playerID) { let playerColor = playerID > -1 ? rgbToGuiColor(g_DisplayedPlayerColors[playerID]) : "white"; - return coloredText(username || translate("Unknown Player"), playerColor); + return setStringTags(username || translate("Unknown Player"), { "color": playerColor }); } /** Index: binaries/data/mods/public/gui/session/selection_details.js =================================================================== --- binaries/data/mods/public/gui/session/selection_details.js +++ binaries/data/mods/public/gui/session/selection_details.js @@ -171,13 +171,13 @@ if (entState.promotion.curr < entState.promotion.req) Engine.GetGUIObjectByName("experience").tooltip = sprintf(translate("%(experience)s %(current)s / %(required)s"), { - "experience": "[font=\"sans-bold-13\"]" + translate("Experience:") + "[/font]", + "experience": headerFont(translate("Experience:")), "current": Math.floor(entState.promotion.curr), "required": entState.promotion.req }); else Engine.GetGUIObjectByName("experience").tooltip = sprintf(translate("%(experience)s %(current)s"), { - "experience": "[font=\"sans-bold-13\"]" + translate("Experience:") + "[/font]", + "experience": headerFont(translate("Experience:")), "current": Math.floor(entState.promotion.curr) }); } @@ -299,7 +299,7 @@ let iconTooltips = []; if (genericName) - iconTooltips.push("[font=\"sans-bold-16\"]" + genericName + "[/font]"); + iconTooltips.push(setStringTags(genericName, g_TooltipTextFormats.nameGeneric)); iconTooltips = iconTooltips.concat([ getVisibleEntityClassesFormatted, Index: binaries/data/mods/public/gui/session/selection_panels.js =================================================================== --- binaries/data/mods/public/gui/session/selection_panels.js +++ binaries/data/mods/public/gui/session/selection_panels.js @@ -319,6 +319,7 @@ performFormation(unitIds, data.item); }; + // This is called often, so we do not use setStringTags here, since it would create a new object on every call. let tooltip = translate(formationInfo.name); if (!formationOk && formationInfo.tooltip) tooltip += "\n" + coloredText(translate(formationInfo.tooltip), "red"); @@ -580,7 +581,7 @@ let tooltip = getEntityNames(template); if (queuedItem.neededSlots) { - tooltip += "\n" + coloredText(translate("Insufficient population capacity:"), "red"); + tooltip += "\n" + setStringTags(translate("Insufficient population capacity:"), g_TooltipTextFormats.insufficient); tooltip += "\n" + sprintf(translate("%(population)s %(neededSlots)s"), { "population": resourceIcon("population"), "neededSlots": queuedItem.neededSlots @@ -906,8 +907,8 @@ let unitIds = data.unitEntStates.map(state => state.id); data.button.onPress = function() { performStance(unitIds, data.item); }; - data.button.tooltip = getStanceDisplayName(data.item) + "\n" + - "[font=\"sans-13\"]" + getStanceTooltip(data.item) + "[/font]"; + data.button.tooltip = headerFont(getStanceDisplayName(data.item)) + "\n" + + bodyFont(getStanceTooltip(data.item)); data.guiSelection.hidden = !Engine.GuiInterfaceCall("IsStanceSelected", { "ents": unitIds, @@ -965,9 +966,10 @@ data.countDisplay.caption = trainNum > 1 ? trainNum : ""; let tooltips = [ - "[font=\"sans-bold-16\"]" + - colorizeHotkey("%(hotkey)s", "session.queueunit." + (data.i + 1)) + - "[/font]" + " " + getEntityNamesFormatted(template), + setStringTags( + colorizeHotkey("%(hotkey)s", "session.queueunit." + (data.i + 1)), + g_TooltipTextFormats.nameGeneric + ) + " " + getEntityNamesFormatted(template), getVisibleEntityClassesFormatted(template), getAurasTooltip(template), getEntityTooltip(template), Index: binaries/data/mods/public/gui/session/selection_panels_helpers.js =================================================================== --- binaries/data/mods/public/gui/session/selection_panels_helpers.js +++ binaries/data/mods/public/gui/session/selection_panels_helpers.js @@ -100,6 +100,8 @@ "limit": trainEntLimit }); + // This is called often so we do not use setStringTags here, for it would need + // to create a new object every call. if (trainEntCount >= trainEntLimit) text = coloredText(text, "red"); @@ -161,16 +163,14 @@ else batchString = translate("%(action)s to train %(number)s."); - return "[font=\"sans-13\"]" + - setStringTags( + return bodyFont(setStringTags( sprintf(batchString, { - "action": "[font=\"sans-bold-13\"]" + translate("Shift-click") + "[/font]", + "action": headerFont(translate("Shift-click")), "number": totalBatchTrainingCount, "fullBatch": fullBatchesString, "remainderBatch": remainderBatch }), - g_HotkeyTags) + - "[/font]"; + g_HotkeyTags)); } /** Index: binaries/data/mods/public/gui/session/selection_panels_left/stance_panel.xml =================================================================== --- binaries/data/mods/public/gui/session/selection_panels_left/stance_panel.xml +++ binaries/data/mods/public/gui/session/selection_panels_left/stance_panel.xml @@ -7,7 +7,7 @@ > -