Use Tuple syntax

This commit is contained in:
teinarss
2020-08-02 13:41:03 +02:00
committed by Paul Chote
parent 8a74f6ea18
commit 19b02875c7
90 changed files with 738 additions and 826 deletions

View File

@@ -20,25 +20,25 @@ namespace OpenRA.Mods.Common.Widgets
public class LabelWithHighlightWidget : LabelWidget
{
public Color HighlightColor = ChromeMetrics.Get<Color>("TextHighlightColor");
readonly CachedTransform<string, Pair<string, bool>[]> textComponents;
readonly CachedTransform<string, (string Text, bool Highlighted)[]> textComponents;
[ObjectCreator.UseCtor]
public LabelWithHighlightWidget()
: base()
{
textComponents = new CachedTransform<string, Pair<string, bool>[]>(MakeComponents);
textComponents = new CachedTransform<string, (string, bool)[]>(MakeComponents);
}
protected LabelWithHighlightWidget(LabelWithHighlightWidget other)
: base(other)
{
HighlightColor = other.HighlightColor;
textComponents = new CachedTransform<string, Pair<string, bool>[]>(MakeComponents);
textComponents = new CachedTransform<string, (string, bool)[]>(MakeComponents);
}
Pair<string, bool>[] MakeComponents(string text)
(string, bool)[] MakeComponents(string text)
{
List<Pair<string, bool>> components = new List<Pair<string, bool>>();
var components = new List<(string, bool)>();
foreach (var l in text.Split(new[] { "\\n" }, StringSplitOptions.None))
{
var line = l;
@@ -54,18 +54,18 @@ namespace OpenRA.Mods.Common.Widgets
{
// Normal line segment before highlight
var lineNormal = line.Substring(0, highlightStart);
components.Add(Pair.New(lineNormal, false));
components.Add((lineNormal, false));
}
// Highlight line segment
var lineHighlight = line.Substring(highlightStart + 1, highlightEnd - highlightStart - 1);
components.Add(Pair.New(lineHighlight, true));
components.Add((lineHighlight, true));
line = line.Substring(highlightEnd + 1);
}
else
{
// Final normal line segment
components.Add(Pair.New(line, false));
components.Add((line, false));
break;
}
}
@@ -79,8 +79,8 @@ namespace OpenRA.Mods.Common.Widgets
var advance = 0;
foreach (var c in textComponents.Update(text))
{
base.DrawInner(c.First, font, c.Second ? HighlightColor : color, position + new int2(advance, 0));
advance += font.Measure(c.First).X;
base.DrawInner(c.Text, font, c.Highlighted ? HighlightColor : color, position + new int2(advance, 0));
advance += font.Measure(c.Text).X;
}
}

View File

@@ -66,10 +66,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
playerPanel.RemoveChildren();
var teams = world.Players.Where(p => !p.NonCombatant && p.Playable)
.Select(p => new Pair<Player, PlayerStatistics>(p, p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
.OrderByDescending(p => p.Second != null ? p.Second.Experience : 0)
.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.First.ClientIndex) ?? new Session.Client()).Team)
.OrderByDescending(g => g.Sum(gg => gg.Second != null ? gg.Second.Experience : 0));
.Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
.OrderByDescending(p => p.PlayerStatistics != null ? p.PlayerStatistics.Experience : 0)
.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
.OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics != null ? gg.PlayerStatistics.Experience : 0));
foreach (var t in teams)
{
@@ -79,7 +79,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
teamHeader.Get<LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key);
var teamRating = teamHeader.Get<LabelWidget>("TEAM_SCORE");
var scoreCache = new CachedTransform<int, string>(s => s.ToString());
var teamMemberScores = t.Select(tt => tt.Second).Where(s => s != null).ToArray().Select(s => s.Experience);
var teamMemberScores = t.Select(tt => tt.PlayerStatistics).Where(s => s != null).ToArray().Select(s => s.Experience);
teamRating.GetText = () => scoreCache.Update(teamMemberScores.Sum());
playerPanel.AddChild(teamHeader);
@@ -87,7 +87,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
foreach (var p in t.ToList())
{
var pp = p.First;
var pp = p.Player;
var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex);
var item = playerTemplate.Clone();
LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer);
@@ -110,7 +110,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
}
var scoreCache = new CachedTransform<int, string>(s => s.ToString());
item.Get<LabelWidget>("SCORE").GetText = () => scoreCache.Update(p.Second != null ? p.Second.Experience : 0);
item.Get<LabelWidget>("SCORE").GetText = () => scoreCache.Update(p.PlayerStatistics != null ? p.PlayerStatistics.Experience : 0);
playerPanel.AddChild(item);
}
@@ -133,13 +133,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var nameFont = Game.Renderer.Fonts[nameLabel.Font];
var suffixLength = new CachedTransform<string, int>(s => nameFont.Measure(s).X);
var name = new CachedTransform<Pair<string, string>, string>(c =>
WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - suffixLength.Update(c.Second), nameFont) + c.Second);
var name = new CachedTransform<(string Name, string Suffix), string>(c =>
WidgetUtils.TruncateText(c.Name, nameLabel.Bounds.Width - suffixLength.Update(c.Suffix), nameFont) + c.Suffix);
nameLabel.GetText = () =>
{
var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : "";
return name.Update(Pair.New(client.Name, suffix));
return name.Update((client.Name, suffix));
};
var kickButton = item.Get<ButtonWidget>("KICK");

View File

@@ -442,8 +442,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (powerRes != null)
{
var power = template.Get<LabelWidget>("POWER");
var powerText = new CachedTransform<Pair<int, int>, string>(p => p.First + "/" + p.Second);
power.GetText = () => powerText.Update(new Pair<int, int>(powerRes.PowerDrained, powerRes.PowerProvided));
var powerText = new CachedTransform<(int PowerDrained, int PowerProvided), string>(p => p.PowerDrained + "/" + p.PowerProvided);
power.GetText = () => powerText.Update((powerRes.PowerDrained, powerRes.PowerProvided));
power.GetColor = () => GetPowerColor(powerRes.PowerState);
}

View File

@@ -162,15 +162,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
}
/// <summary>Splits a string into two parts on the first instance of a given token.</summary>
static Pair<string, string> SplitOnFirstToken(string input, string token = "\\n")
static (string First, string Second) SplitOnFirstToken(string input, string token = "\\n")
{
if (string.IsNullOrEmpty(input))
return Pair.New<string, string>(null, null);
return (null, null);
var split = input.IndexOf(token, StringComparison.Ordinal);
var first = split > 0 ? input.Substring(0, split) : input;
var second = split > 0 ? input.Substring(split + token.Length) : null;
return Pair.New(first, second);
return (first, second);
}
public static void ShowFactionDropDown(DropDownButtonWidget dropdown, Session.Client client,
@@ -253,9 +253,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var spawnSize = ChromeProvider.GetImage("lobby-bits", "spawn-unclaimed").Size.XY;
var selectedSpawn = preview.SpawnPoints
.Select((sp, i) => Pair.New(mapPreview.ConvertToPreview(sp, preview.GridType), i))
.Where(a => ((a.First - mi.Location).ToFloat2() / spawnSize * 2).LengthSquared <= 1)
.Select(a => a.Second + 1)
.Select((sp, i) => (SpawnLocation: mapPreview.ConvertToPreview(sp, preview.GridType), Index: i))
.Where(a => ((a.SpawnLocation - mi.Location).ToFloat2() / spawnSize * 2).LengthSquared <= 1)
.Select(a => a.Index + 1)
.FirstOrDefault();
var locals = orderManager.LobbyInfo.Clients.Where(c => c.Index == orderManager.LocalClient.Index || (Game.IsHost && c.Bot != null));

View File

@@ -12,7 +12,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic
@@ -182,20 +181,20 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// Order categories alphabetically
var categories = categoryDict
.Select(kv => Pair.New(kv.Key, kv.Value))
.OrderBy(p => p.First)
.Select(kv => (Category: kv.Key, Count: kv.Value))
.OrderBy(p => p.Category)
.ToList();
// 'all game types' extra item
categories.Insert(0, Pair.New(null as string, tabMaps[tab].Count()));
categories.Insert(0, (null as string, tabMaps[tab].Count()));
Func<Pair<string, int>, string> showItem = x => "{0} ({1})".F(x.First ?? "All Maps", x.Second);
Func<(string Category, int Count), string> showItem = x => "{0} ({1})".F(x.Category ?? "All Maps", x.Count);
Func<Pair<string, int>, ScrollItemWidget, ScrollItemWidget> setupItem = (ii, template) =>
Func<(string Category, int Count), ScrollItemWidget, ScrollItemWidget> setupItem = (ii, template) =>
{
var item = ScrollItemWidget.Setup(template,
() => category == ii.First,
() => { category = ii.First; EnumerateMaps(tab, itemTemplate); });
() => category == ii.Category,
() => { category = ii.Category; EnumerateMaps(tab, itemTemplate); });
item.Get<LabelWidget>("LABEL").GetText = () => showItem(ii);
return item;
};
@@ -205,9 +204,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
gameModeDropdown.GetText = () =>
{
var item = categories.FirstOrDefault(m => m.First == category);
if (item == default(Pair<string, int>))
item.First = "No matches";
var item = categories.FirstOrDefault(m => m.Category == category);
if (item == default((string, int)))
item.Category = "No matches";
return showItem(item);
};

View File

@@ -138,25 +138,25 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (ddb != null)
{
// Using list to maintain the order
var options = new List<Pair<GameType, string>>
var options = new List<(GameType GameType, string Text)>
{
Pair.New(GameType.Any, ddb.GetText()),
Pair.New(GameType.Singleplayer, "Singleplayer"),
Pair.New(GameType.Multiplayer, "Multiplayer")
(GameType.Any, ddb.GetText()),
(GameType.Singleplayer, "Singleplayer"),
(GameType.Multiplayer, "Multiplayer")
};
var lookup = options.ToDictionary(kvp => kvp.First, kvp => kvp.Second);
var lookup = options.ToDictionary(kvp => kvp.GameType, kvp => kvp.Text);
ddb.GetText = () => lookup[filter.Type];
ddb.OnMouseDown = _ =>
{
Func<Pair<GameType, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
Func<(GameType GameType, string Text), ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
{
var item = ScrollItemWidget.Setup(
tpl,
() => filter.Type == option.First,
() => { filter.Type = option.First; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Second;
() => filter.Type == option.GameType,
() => { filter.Type = option.GameType; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Text;
return item;
};
@@ -171,28 +171,28 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (ddb != null)
{
// Using list to maintain the order
var options = new List<Pair<DateType, string>>
var options = new List<(DateType DateType, string Text)>
{
Pair.New(DateType.Any, ddb.GetText()),
Pair.New(DateType.Today, "Today"),
Pair.New(DateType.LastWeek, "Last 7 days"),
Pair.New(DateType.LastFortnight, "Last 14 days"),
Pair.New(DateType.LastMonth, "Last 30 days")
(DateType.Any, ddb.GetText()),
(DateType.Today, "Today"),
(DateType.LastWeek, "Last 7 days"),
(DateType.LastFortnight, "Last 14 days"),
(DateType.LastMonth, "Last 30 days")
};
var lookup = options.ToDictionary(kvp => kvp.First, kvp => kvp.Second);
var lookup = options.ToDictionary(kvp => kvp.DateType, kvp => kvp.Text);
ddb.GetText = () => lookup[filter.Date];
ddb.OnMouseDown = _ =>
{
Func<Pair<DateType, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
Func<(DateType DateType, string Text), ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
{
var item = ScrollItemWidget.Setup(
tpl,
() => filter.Date == option.First,
() => { filter.Date = option.First; ApplyFilter(); });
() => filter.Date == option.DateType,
() => { filter.Date = option.DateType; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Second;
item.Get<LabelWidget>("LABEL").GetText = () => option.Text;
return item;
};
@@ -207,27 +207,27 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (ddb != null)
{
// Using list to maintain the order
var options = new List<Pair<DurationType, string>>
var options = new List<(DurationType DurationType, string Text)>
{
Pair.New(DurationType.Any, ddb.GetText()),
Pair.New(DurationType.VeryShort, "Under 5 min"),
Pair.New(DurationType.Short, "Short (10 min)"),
Pair.New(DurationType.Medium, "Medium (30 min)"),
Pair.New(DurationType.Long, "Long (60+ min)")
(DurationType.Any, ddb.GetText()),
(DurationType.VeryShort, "Under 5 min"),
(DurationType.Short, "Short (10 min)"),
(DurationType.Medium, "Medium (30 min)"),
(DurationType.Long, "Long (60+ min)")
};
var lookup = options.ToDictionary(kvp => kvp.First, kvp => kvp.Second);
var lookup = options.ToDictionary(kvp => kvp.DurationType, kvp => kvp.Text);
ddb.GetText = () => lookup[filter.Duration];
ddb.OnMouseDown = _ =>
{
Func<Pair<DurationType, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
Func<(DurationType DurationType, string Text), ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
{
var item = ScrollItemWidget.Setup(
tpl,
() => filter.Duration == option.First,
() => { filter.Duration = option.First; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Second;
() => filter.Duration == option.DurationType,
() => { filter.Duration = option.DurationType; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Text;
return item;
};
@@ -244,25 +244,25 @@ namespace OpenRA.Mods.Common.Widgets.Logic
ddb.IsDisabled = () => string.IsNullOrEmpty(filter.PlayerName);
// Using list to maintain the order
var options = new List<Pair<WinState, string>>
var options = new List<(WinState WinState, string Text)>
{
Pair.New(WinState.Undefined, ddb.GetText()),
Pair.New(WinState.Lost, "Defeat"),
Pair.New(WinState.Won, "Victory")
(WinState.Undefined, ddb.GetText()),
(WinState.Lost, "Defeat"),
(WinState.Won, "Victory")
};
var lookup = options.ToDictionary(kvp => kvp.First, kvp => kvp.Second);
var lookup = options.ToDictionary(kvp => kvp.WinState, kvp => kvp.Text);
ddb.GetText = () => lookup[filter.Outcome];
ddb.OnMouseDown = _ =>
{
Func<Pair<WinState, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
Func<(WinState WinState, string Text), ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
{
var item = ScrollItemWidget.Setup(
tpl,
() => filter.Outcome == option.First,
() => { filter.Outcome = option.First; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Second;
() => filter.Outcome == option.WinState,
() => { filter.Outcome = option.WinState; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Text;
return item;
};

View File

@@ -14,7 +14,6 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic
@@ -26,22 +25,22 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// Increment the version number when adding new stats
const int SystemInformationVersion = 4;
static Dictionary<string, Pair<string, string>> GetSystemInformation()
static Dictionary<string, (string Label, string Value)> GetSystemInformation()
{
var lang = CultureInfo.InstalledUICulture.TwoLetterISOLanguageName;
return new Dictionary<string, Pair<string, string>>()
return new Dictionary<string, (string, string)>()
{
{ "id", Pair.New("Anonymous ID", Game.Settings.Debug.UUID) },
{ "platform", Pair.New("OS Type", Platform.CurrentPlatform.ToString()) },
{ "os", Pair.New("OS Version", Environment.OSVersion.ToString()) },
{ "x64", Pair.New("OS is 64 bit", Environment.Is64BitOperatingSystem.ToString()) },
{ "x64process", Pair.New("Process is 64 bit", Environment.Is64BitProcess.ToString()) },
{ "runtime", Pair.New(".NET Runtime", Platform.RuntimeVersion) },
{ "gl", Pair.New("OpenGL Version", Game.Renderer.GLVersion) },
{ "windowsize", Pair.New("Window Size", "{0}x{1}".F(Game.Renderer.NativeResolution.Width, Game.Renderer.NativeResolution.Height)) },
{ "windowscale", Pair.New("Window Scale", Game.Renderer.NativeWindowScale.ToString("F2", CultureInfo.InvariantCulture)) },
{ "uiscale", Pair.New("UI Scale", Game.Settings.Graphics.UIScale.ToString("F2", CultureInfo.InvariantCulture)) },
{ "lang", Pair.New("System Language", lang) }
{ "id", ("Anonymous ID", Game.Settings.Debug.UUID) },
{ "platform", ("OS Type", Platform.CurrentPlatform.ToString()) },
{ "os", ("OS Version", Environment.OSVersion.ToString()) },
{ "x64", ("OS is 64 bit", Environment.Is64BitOperatingSystem.ToString()) },
{ "x64process", ("Process is 64 bit", Environment.Is64BitProcess.ToString()) },
{ "runtime", (".NET Runtime", Platform.RuntimeVersion) },
{ "gl", ("OpenGL Version", Game.Renderer.GLVersion) },
{ "windowsize", ("Window Size", "{0}x{1}".F(Game.Renderer.NativeResolution.Width, Game.Renderer.NativeResolution.Height)) },
{ "windowscale", ("Window Scale", Game.Renderer.NativeWindowScale.ToString("F2", CultureInfo.InvariantCulture)) },
{ "uiscale", ("UI Scale", Game.Settings.Graphics.UIScale.ToString("F2", CultureInfo.InvariantCulture)) },
{ "lang", ("System Language", lang) }
};
}
@@ -57,7 +56,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
return "&sysinfoversion={0}&".F(SystemInformationVersion)
+ GetSystemInformation()
.Select(kv => kv.Key + "=" + Uri.EscapeUriString(kv.Value.Second))
.Select(kv => kv.Key + "=" + Uri.EscapeUriString(kv.Value.Value))
.JoinWith("&");
}
@@ -75,7 +74,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
foreach (var info in GetSystemInformation().Values)
{
var label = template.Clone() as LabelWidget;
var text = info.First + ": " + info.Second;
var text = info.Label + ": " + info.Value;
label.GetText = () => text;
sysInfoData.AddChild(label);
}

View File

@@ -206,8 +206,8 @@ namespace OpenRA.Mods.Common.Widgets
void UpdateTerrainColor(MPos uv)
{
var colorPair = playerRadarTerrain != null && playerRadarTerrain.IsInitialized ? playerRadarTerrain[uv] : PlayerRadarTerrain.GetColor(world.Map, uv);
var leftColor = colorPair.First;
var rightColor = colorPair.Second;
var leftColor = colorPair.Left;
var rightColor = colorPair.Right;
var stride = radarSheet.Size.Width;
@@ -386,7 +386,7 @@ namespace OpenRA.Mods.Common.Widgets
var stride = radarSheet.Size.Width;
Array.Clear(radarData, 4 * actorSprite.Bounds.Top * stride, 4 * actorSprite.Bounds.Height * stride);
var cells = new List<Pair<CPos, Color>>();
var cells = new List<(CPos Cell, Color Color)>();
unsafe
{
@@ -403,11 +403,11 @@ namespace OpenRA.Mods.Common.Widgets
t.Trait.PopulateRadarSignatureCells(t.Actor, cells);
foreach (var cell in cells)
{
if (!world.Map.Contains(cell.First))
if (!world.Map.Contains(cell.Cell))
continue;
var uv = cell.First.ToMPos(world.Map.Grid.Type);
var color = cell.Second.ToArgb();
var uv = cell.Cell.ToMPos(world.Map.Grid.Type);
var color = cell.Color.ToArgb();
if (isRectangularIsometric)
{
// Odd rows are shifted right by 1px

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.Widgets
readonly int timestep;
readonly IEnumerable<SupportPowerInstance> powers;
readonly Color bgDark, bgLight;
Pair<string, Color>[] texts;
(string Text, Color Color)[] texts;
[ObjectCreator.UseCtor]
public SupportPowerTimerWidget(World world)
@@ -67,7 +67,7 @@ namespace OpenRA.Mods.Common.Widgets
var color = !p.Ready || Game.LocalTick % 50 < 25 ? playerColor : Color.White;
return Pair.New(text, color);
return (text, color);
}).ToArray();
}
@@ -80,8 +80,8 @@ namespace OpenRA.Mods.Common.Widgets
foreach (var t in texts)
{
var font = Game.Renderer.Fonts[Font];
font.DrawTextWithShadow(t.First, new float2(Bounds.Location) + new float2(0, y), t.Second, bgDark, bgLight, 1);
y += (font.Measure(t.First).Y + 5) * (int)Order;
font.DrawTextWithShadow(t.Text, new float2(Bounds.Location) + new float2(0, y), t.Color, bgDark, bgLight, 1);
y += (font.Measure(t.Text).Y + 5) * (int)Order;
}
}

View File

@@ -337,19 +337,19 @@ namespace OpenRA.Mods.Common.Widgets
{
var client = p.World.LobbyInfo.ClientWithIndex(p.ClientIndex);
var nameFont = Game.Renderer.Fonts[label.Font];
var name = new CachedTransform<Tuple<string, WinState, Session.ClientState>, string>(c =>
var name = new CachedTransform<(string Name, WinState WinState, Session.ClientState ClientState), string>(c =>
{
var suffix = c.Item2 == WinState.Undefined ? "" : " (" + c.Item2 + ")";
if (c.Item3 == Session.ClientState.Disconnected)
var suffix = c.WinState == WinState.Undefined ? "" : " (" + c.Item2 + ")";
if (c.ClientState == Session.ClientState.Disconnected)
suffix = " (Gone)";
return TruncateText(c.Item1, label.Bounds.Width - nameFont.Measure(suffix).X, nameFont) + suffix;
return TruncateText(c.Name, label.Bounds.Width - nameFont.Measure(suffix).X, nameFont) + suffix;
});
label.GetText = () =>
{
var clientState = client != null ? client.State : Session.ClientState.Ready;
return name.Update(Tuple.Create(p.PlayerName, p.WinState, clientState));
return name.Update((p.PlayerName, p.WinState, clientState));
};
}
}