diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj
index a6ab5f21dd..518f35eb45 100644
--- a/OpenRA.Game/OpenRA.Game.csproj
+++ b/OpenRA.Game/OpenRA.Game.csproj
@@ -316,7 +316,6 @@
-
diff --git a/OpenRA.Game/Support/Evaluator.cs b/OpenRA.Game/Support/Evaluator.cs
deleted file mode 100644
index 40a235634c..0000000000
--- a/OpenRA.Game/Support/Evaluator.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-#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.Linq;
-
-namespace OpenRA.Support
-{
- public static class Evaluator
- {
- public static int Evaluate(string expr)
- {
- return Evaluate(expr, new Dictionary());
- }
-
- public static int Evaluate(string expr, Dictionary syms)
- {
- var toks = Tokens(expr, "+-*/()");
- var postfix = ToPostfix(toks, syms);
-
- var s = new Stack();
-
- foreach (var t in postfix)
- {
- switch (t[0])
- {
- case '+': ApplyBinop(s, (x, y) => y + x); break;
- case '-': ApplyBinop(s, (x, y) => y - x); break;
- case '*': ApplyBinop(s, (x, y) => y * x); break;
- case '/': ApplyBinop(s, (x, y) => y / x); break;
- default: s.Push(Exts.ParseIntegerInvariant(t)); break;
- }
- }
-
- return s.Pop();
- }
-
- static void ApplyBinop(Stack s, Func f)
- {
- var x = s.Pop();
- var y = s.Pop();
- s.Push(f(x, y));
- }
-
- static IEnumerable ToPostfix(IEnumerable toks, Dictionary syms)
- {
- var s = new Stack();
- foreach (var t in toks)
- {
- if (t[0] == '(') s.Push(t);
- else if (t[0] == ')')
- {
- var temp = "";
- while ((temp = s.Pop()) != "(") yield return temp;
- }
- else if (char.IsNumber(t[0])) yield return t;
- else if (char.IsLetter(t[0]))
- {
- if (!syms.ContainsKey(t))
- throw new InvalidOperationException("Substitution `{0}` undefined".F(t));
-
- yield return syms[t].ToString();
- }
- else
- {
- while (s.Count > 0 && Prec[t] <= Prec[s.Peek()]) yield return s.Pop();
- s.Push(t);
- }
- }
-
- while (s.Count > 0) yield return s.Pop();
- }
-
- static readonly Dictionary Prec
- = new Dictionary { { "+", 0 }, { "-", 0 }, { "*", 1 }, { "/", 1 }, { "(", -1 } };
-
- static IEnumerable Tokens(string expr, string ops)
- {
- var s = "";
- foreach (var c in expr)
- {
- if (char.IsWhiteSpace(c))
- {
- if (s != "") yield return s;
- s = "";
- }
- else if (ops.Contains(c))
- {
- if (s != "") yield return s;
- s = "";
- yield return "" + c;
- }
- else
- s += c;
- }
-
- if (s != "") yield return s;
- }
- }
-}
diff --git a/OpenRA.Game/Widgets/Widget.cs b/OpenRA.Game/Widgets/Widget.cs
index ca7e85bb7b..34911a4e4a 100644
--- a/OpenRA.Game/Widgets/Widget.cs
+++ b/OpenRA.Game/Widgets/Widget.cs
@@ -196,10 +196,10 @@ namespace OpenRA.Widgets
// Info defined in YAML
public string Id = null;
- public string X = "0";
- public string Y = "0";
- public string Width = "0";
- public string Height = "0";
+ public IntegerExpression X;
+ public IntegerExpression Y;
+ public IntegerExpression Width;
+ public IntegerExpression Height;
public string[] Logic = { };
public ChromeLogic[] LogicObjects { get; private set; }
public bool Visible = true;
@@ -275,16 +275,17 @@ namespace OpenRA.Widgets
substitutions.Add("PARENT_LEFT", parentBounds.Left);
substitutions.Add("PARENT_TOP", parentBounds.Top);
substitutions.Add("PARENT_BOTTOM", parentBounds.Height);
- var width = Evaluator.Evaluate(Width, substitutions);
- var height = Evaluator.Evaluate(Height, substitutions);
+
+ var readOnlySubstitutions = new ReadOnlyDictionary(substitutions);
+ var width = Width != null ? Width.Evaluate(readOnlySubstitutions) : 0;
+ var height = Height != null ? Height.Evaluate(readOnlySubstitutions) : 0;
substitutions.Add("WIDTH", width);
substitutions.Add("HEIGHT", height);
- Bounds = new Rectangle(Evaluator.Evaluate(X, substitutions),
- Evaluator.Evaluate(Y, substitutions),
- width,
- height);
+ var x = X != null ? X.Evaluate(readOnlySubstitutions) : 0;
+ var y = Y != null ? Y.Evaluate(readOnlySubstitutions) : 0;
+ Bounds = new Rectangle(x, y, width, height);
}
public void PostInit(WidgetArgs args)