diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 269c8146c5..650ab2e15a 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -812,6 +812,9 @@ + + + diff --git a/OpenRA.Mods.Common/Widgets/Logic/ButtonTooltipWithDescHighlightLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ButtonTooltipWithDescHighlightLogic.cs new file mode 100644 index 0000000000..d47e0f0c44 --- /dev/null +++ b/OpenRA.Mods.Common/Widgets/Logic/ButtonTooltipWithDescHighlightLogic.cs @@ -0,0 +1,123 @@ +#region Copyright & License Information +/* + * Copyright 2007-2017 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using OpenRA.Widgets; + +namespace OpenRA.Mods.Common.Widgets.Logic +{ + public class ButtonTooltipWithDescHighlightLogic : ChromeLogic + { + [ObjectCreator.UseCtor] + public ButtonTooltipWithDescHighlightLogic(Widget widget, ButtonWidget button, Dictionary logicArgs) + { + var label = widget.Get("LABEL"); + var font = Game.Renderer.Fonts[label.Font]; + var text = button.GetTooltipText(); + var labelWidth = font.Measure(text).X; + + label.GetText = () => text; + label.Bounds.Width = labelWidth; + widget.Bounds.Width = 2 * label.Bounds.X + labelWidth; + + if (button.Key.IsValid()) + { + var hotkey = widget.Get("HOTKEY"); + hotkey.Visible = true; + + var hotkeyLabel = "({0})".F(button.Key.DisplayString()); + hotkey.GetText = () => hotkeyLabel; + hotkey.Bounds.X = labelWidth + 2 * label.Bounds.X; + + widget.Bounds.Width = hotkey.Bounds.X + label.Bounds.X + font.Measure(hotkeyLabel).X; + } + + var desc = button.GetTooltipDesc(); + if (!string.IsNullOrEmpty(desc)) + { + var descTemplate = widget.Get("DESC"); + var highlightColor = FieldLoader.GetValue("Highlight", logicArgs["Highlight"].Value); + widget.RemoveChild(descTemplate); + + var descFont = Game.Renderer.Fonts[descTemplate.Font]; + var descWidth = 0; + var descOffset = descTemplate.Bounds.Y; + + foreach (var l in desc.Split(new[] { "\\n" }, StringSplitOptions.None)) + { + var line = l; + var lineWidth = 0; + var xOffset = descTemplate.Bounds.X; + + while (line.Length > 0) + { + var highlightStart = line.IndexOf('{'); + var highlightEnd = line.IndexOf('}', 0); + + if (highlightStart > 0 && highlightEnd > highlightStart) + { + if (highlightStart > 0) + { + // Normal line segment before highlight + var lineNormal = line.Substring(0, highlightStart); + var lineNormalWidth = descFont.Measure(lineNormal).X; + var lineNormalLabel = (LabelWidget)descTemplate.Clone(); + lineNormalLabel.GetText = () => lineNormal; + lineNormalLabel.Bounds.X = descTemplate.Bounds.X + lineWidth; + lineNormalLabel.Bounds.Y = descOffset; + lineNormalLabel.Bounds.Width = lineNormalWidth; + widget.AddChild(lineNormalLabel); + + lineWidth += lineNormalWidth; + } + + // Highlight line segment + var lineHighlight = line.Substring(highlightStart + 1, highlightEnd - highlightStart - 1); + var lineHighlightWidth = descFont.Measure(lineHighlight).X; + var lineHighlightLabel = (LabelWidget)descTemplate.Clone(); + lineHighlightLabel.GetText = () => lineHighlight; + lineHighlightLabel.GetColor = () => highlightColor; + lineHighlightLabel.Bounds.X = descTemplate.Bounds.X + lineWidth; + lineHighlightLabel.Bounds.Y = descOffset; + lineHighlightLabel.Bounds.Width = lineHighlightWidth; + widget.AddChild(lineHighlightLabel); + + lineWidth += lineHighlightWidth; + line = line.Substring(highlightEnd + 1); + } + else + { + // Final normal line segment + var lineLabel = (LabelWidget)descTemplate.Clone(); + var width = descFont.Measure(line).X; + lineLabel.GetText = () => line; + lineLabel.Bounds.X = descTemplate.Bounds.X + lineWidth; + lineLabel.Bounds.Y = descOffset; + widget.AddChild(lineLabel); + + lineWidth += width; + break; + } + } + + descWidth = Math.Max(descWidth, lineWidth); + + descOffset += descTemplate.Bounds.Height; + } + + widget.Bounds.Width = Math.Max(widget.Bounds.Width, descTemplate.Bounds.X * 2 + descWidth); + widget.Bounds.Height += descOffset - descTemplate.Bounds.Y + descTemplate.Bounds.X; + } + } + } +} \ No newline at end of file