diff --git a/OpenRA.Game/Widgets/WidgetUtils.cs b/OpenRA.Game/Widgets/WidgetUtils.cs index ac8c1ac7b2..95f467458e 100644 --- a/OpenRA.Game/Widgets/WidgetUtils.cs +++ b/OpenRA.Game/Widgets/WidgetUtils.cs @@ -227,6 +227,22 @@ namespace OpenRA.Widgets return text; } + public static string TruncateText(string text, int width, SpriteFont font) + { + var trimmedWidth = font.Measure(text).X; + if (trimmedWidth <= width) + return text; + + var trimmed = text; + while (trimmedWidth > width && trimmed.Length > 3) + { + trimmed = text.Substring(0, trimmed.Length - 4) + "..."; + trimmedWidth = font.Measure(trimmed).X; + } + + return trimmed; + } + public static Action Once(Action a) { return () => { if (a != null) { a(); a = null; } }; } public static string ChooseInitialMap(string initialUid) @@ -242,6 +258,32 @@ namespace OpenRA.Widgets } } + public class CachedTransform + { + readonly Func transform; + + bool initialized; + T lastInput; + U lastOutput; + + public CachedTransform(Func transform) + { + this.transform = transform; + } + + public U Update(T input) + { + if (initialized && ((input == null && lastInput == null) || input.Equals(lastInput))) + return lastOutput; + + lastInput = input; + lastOutput = transform(input); + initialized = true; + + return lastOutput; + } + } + [Flags] public enum PanelSides { diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyMapPreviewLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyMapPreviewLogic.cs index 3ed4034e91..a73adff1e3 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyMapPreviewLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyMapPreviewLogic.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using OpenRA.Network; using OpenRA.Widgets; @@ -28,17 +29,25 @@ namespace OpenRA.Mods.Common.Widgets.Logic preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); - var title = available.GetOrNull("MAP_TITLE"); - if (title != null) - title.GetText = () => lobby.Map.Title; + var titleLabel = available.GetOrNull("MAP_TITLE"); + if (titleLabel != null) + { + var font = Game.Renderer.Fonts[titleLabel.Font]; + var title = new CachedTransform(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); + titleLabel.GetText = () => title.Update(lobby.Map); + } - var type = available.GetOrNull("MAP_TYPE"); - if (type != null) - type.GetText = () => lobby.Map.Type; + var typeLabel = available.GetOrNull("MAP_TYPE"); + if (typeLabel != null) + typeLabel.GetText = () => lobby.Map.Type; - var author = available.GetOrNull("MAP_AUTHOR"); - if (author != null) - author.GetText = () => "Created by {0}".F(lobby.Map.Author); + var authorLabel = available.GetOrNull("MAP_AUTHOR"); + if (authorLabel != null) + { + var font = Game.Renderer.Fonts[authorLabel.Font]; + var author = new CachedTransform(m => WidgetUtils.TruncateText("Created by {0}".F(lobby.Map.Author), authorLabel.Bounds.Width, font)); + authorLabel.GetText = () => author.Update(lobby.Map); + } } var invalid = widget.GetOrNull("MAP_INVALID"); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs index a6ac86ca3d..4af9cf8755 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs @@ -291,7 +291,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic public static void SetupNameWidget(Widget parent, Session.Slot s, Session.Client c) { var name = parent.Get("NAME"); - name.GetText = () => c.Name; + var font = Game.Renderer.Fonts[name.Font]; + var label = WidgetUtils.TruncateText(c.Name, name.Bounds.Width, font); + name.GetText = () => label; } public static void SetupEditableSlotWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, Ruleset rules) diff --git a/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs index 45349bfcd6..72f5f4b3d8 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs @@ -235,7 +235,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic item.IsVisible = () => item.RenderBounds.IntersectsWith(scrollpanels[tab].RenderBounds); var titleLabel = item.Get("TITLE"); - titleLabel.GetText = () => preview.Title; + if (titleLabel != null) + { + var font = Game.Renderer.Fonts[titleLabel.Font]; + var title = WidgetUtils.TruncateText(preview.Title, titleLabel.Bounds.Width, font); + titleLabel.GetText = () => title; + } var previewWidget = item.Get("PREVIEW"); previewWidget.Preview = () => preview; @@ -246,7 +251,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic var authorWidget = item.GetOrNull("AUTHOR"); if (authorWidget != null) - authorWidget.GetText = () => "Created by {0}".F(preview.Author); + { + var font = Game.Renderer.Fonts[authorWidget.Font]; + var author = WidgetUtils.TruncateText("Created by {0}".F(preview.Author), authorWidget.Bounds.Width, font); + authorWidget.GetText = () => author; + } var sizeWidget = item.GetOrNull("SIZE"); if (sizeWidget != null) diff --git a/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs index 687a8cfd08..0e85b65068 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs @@ -198,7 +198,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic var mapTitle = widget.GetOrNull("SELECTED_MAP"); if (mapTitle != null) - mapTitle.GetText = () => currentMap != null ? currentMap.Title : "No Server Selected"; + { + var font = Game.Renderer.Fonts[mapTitle.Font]; + var title = new CachedTransform(m => m == null ? "No Server Selected" : + WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); + mapTitle.GetText = () => title.Update(currentMap); + } var ip = widget.GetOrNull("SELECTED_IP"); if (ip != null) @@ -219,8 +224,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (modVersion != null) { modVersion.IsVisible = () => currentServer != null; - modVersion.GetText = () => currentServer.ModLabel; modVersion.GetColor = () => currentServer.IsCompatible ? modVersion.TextColor : incompatibleVersionColor; + + var font = Game.Renderer.Fonts[modVersion.Font]; + var version = new CachedTransform(s => WidgetUtils.TruncateText(s.ModLabel, mapTitle.Bounds.Width, font)); + modVersion.GetText = () => version.Update(currentServer); } var players = widget.GetOrNull("SELECTED_PLAYERS"); @@ -358,7 +366,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic var title = item.GetOrNull("TITLE"); if (title != null) { - title.GetText = () => game.Name; + var font = Game.Renderer.Fonts[title.Font]; + var label = WidgetUtils.TruncateText(game.Name, title.Bounds.Width, font); + title.GetText = () => label; title.GetColor = () => canJoin ? title.TextColor : incompatibleGameColor; } diff --git a/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs index 821b28fc95..90962f3d5c 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs @@ -71,9 +71,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic preview.SpawnOccupants = () => selectedSpawns; preview.Preview = () => selectedReplay != null ? selectedReplay.GameInfo.MapPreview : null; - var title = panel.GetOrNull("MAP_TITLE"); - if (title != null) - title.GetText = () => selectedReplay != null ? selectedReplay.GameInfo.MapPreview.Title : null; + var titleLabel = panel.GetOrNull("MAP_TITLE"); + if (titleLabel != null) + { + titleLabel.IsVisible = () => selectedReplay != null; + + var font = Game.Renderer.Fonts[titleLabel.Font]; + var title = new CachedTransform(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); + titleLabel.GetText = () => title.Update(selectedReplay.GameInfo.MapPreview); + } var type = panel.GetOrNull("MAP_TYPE"); if (type != null) diff --git a/OpenRA.Mods.Common/Widgets/Logic/ServerCreationLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ServerCreationLogic.cs index 1f81894f2f..46346f0c88 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ServerCreationLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ServerCreationLogic.cs @@ -52,7 +52,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic }; panel.Get("MAP_PREVIEW").Preview = () => preview; - panel.Get("MAP_NAME").GetText = () => preview.Title; + + var mapTitle = panel.Get("MAP_NAME"); + if (mapTitle != null) + { + var font = Game.Renderer.Fonts[mapTitle.Font]; + var title = new CachedTransform(m => WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); + mapTitle.GetText = () => title.Update(preview); + } } var serverName = panel.Get("SERVER_NAME"); diff --git a/mods/cnc/chrome/mapchooser.yaml b/mods/cnc/chrome/mapchooser.yaml index dba8ae35d4..8efcd90c89 100644 --- a/mods/cnc/chrome/mapchooser.yaml +++ b/mods/cnc/chrome/mapchooser.yaml @@ -89,25 +89,25 @@ Container@MAPCHOOSER_PANEL: IgnoreMouseOver: true IgnoreMouseInput: true Label@TITLE: - X: 2 + X: 4 Y: PARENT_BOTTOM-48 - Width: PARENT_RIGHT-4 + Width: PARENT_RIGHT-8 Align: Center Label@DETAILS: - Width: PARENT_RIGHT-4 - X: 2 + Width: PARENT_RIGHT-8 + X: 4 Y: PARENT_BOTTOM-34 Align: Center Font: Tiny Label@AUTHOR: - Width: PARENT_RIGHT-4 - X: 2 + Width: PARENT_RIGHT-8 + X: 4 Y: PARENT_BOTTOM-22 Align: Center Font: Tiny Label@SIZE: - Width: PARENT_RIGHT-4 - X: 2 + Width: PARENT_RIGHT-8 + X: 4 Y: PARENT_BOTTOM-10 Align: Center Font: Tiny diff --git a/mods/ra/chrome/map-chooser.yaml b/mods/ra/chrome/map-chooser.yaml index d3af5d646d..ac633e9141 100644 --- a/mods/ra/chrome/map-chooser.yaml +++ b/mods/ra/chrome/map-chooser.yaml @@ -60,25 +60,25 @@ Background@MAPCHOOSER_PANEL: IgnoreMouseOver: true IgnoreMouseInput: true Label@TITLE: - X: 2 + X: 4 Y: PARENT_BOTTOM-53 - Width: PARENT_RIGHT-4 + Width: PARENT_RIGHT-8 Align: Center Label@DETAILS: - Width: PARENT_RIGHT-4 - X: 2 + Width: PARENT_RIGHT-8 + X: 4 Y: PARENT_BOTTOM-37 Align: Center Font: Tiny Label@AUTHOR: - Width: PARENT_RIGHT-4 - X: 2 + Width: PARENT_RIGHT-8 + X: 4 Y: PARENT_BOTTOM-25 Align: Center Font: Tiny Label@SIZE: - Width: PARENT_RIGHT-4 - X: 2 + Width: PARENT_RIGHT-8 + X: 4 Y: PARENT_BOTTOM-13 Align: Center Font: Tiny