public void Parse(CompileContext context, System.Xml.XmlNode node) { // We first find the type. type = context.ResolveType(node.Prefix, node.LocalName); if (!Common.IsTypeSameOrDerived(typeof(IWidget), type)) { throw new ParseException(string.Format("The element must be of type IWidget, " + "'{0}' does not implement this interface", type.FullName)); } // Previously, change context was not the same as the type, not they alias. changeType = type; // Now we try to find name attribute. XmlAttribute nameAttr = node.Attributes["Name"]; if (nameAttr != null) { name = nameAttr.InnerText; if (name.Contains(" ")) { throw new ParseException("The name contains spaces, invalid."); } } else { throw new ParseException("Name of widget is required."); } nameAttr = node.Attributes["Style"]; if (nameAttr != null) { styleLink = nameAttr.InnerText; } // We now go for all other attributes and values. foreach (XmlAttribute att in node.Attributes) { if (att.Name == "Name" || att.Name == "Style") { continue; } ProcessAttribute(context, att); } foreach (XmlNode node2 in node.ChildNodes) { ProcessChild(context, node2); } // Registers a widget. context.RegisterWidget(name, this); }
public void Emit(CompileContext context, System.IO.TextWriter writer) { for (int i = 0; i < split.Length; i++) { writer.Write(string.Format("{0}.{1}", enumType.FullName, split[i])); if (i != split.Length - 1) { writer.Write(" | "); } } }
public void Emit(CompileContext context, System.IO.TextWriter writer) { if (value != null) { writer.Write("SharpMedia.Graphics.Colour." + value); } else { writer.Write("new SharpMedia.Graphics.Colour({0}, {1}, {2}, {3})", colour.R.ToString(CultureInfo.InvariantCulture.NumberFormat), colour.G.ToString(CultureInfo.InvariantCulture.NumberFormat), colour.B.ToString(CultureInfo.InvariantCulture.NumberFormat), colour.A.ToString(CultureInfo.InvariantCulture.NumberFormat)); } }
public void Parse(CompileContext context, System.Xml.XmlNode node) { if (node.Attributes["Value"] != null) { ASTScalar scalar = new ASTScalar(); scalar.Parse(context, Token.StackForm(Token.Tokenize(node.Attributes["Value"].InnerText))); data = scalar.Scalar; } else { throw new ParseException("Value of scalar not present in 'Value' attribute."); } }
public void Resolve(CompileContext context, Resolver resolver) { rootWidget = null; for (int i = 0; i < children.Count; i++) { if (children[i] is ASTWidget) { if (rootWidget != null) { throw new ResolveException("Multiple widget root invalid."); } rootWidget = children[i] as ASTWidget; } } }
void ProcessChild(CompileContext context, XmlNode node) { if (node.NodeType != XmlNodeType.Element) { return; } if (node.Prefix == StandardPrefixes.Variable) { throw new NotSupportedException("Variables not yet supported."); } else if (node.Prefix == StandardPrefixes.Value || node.Prefix == StandardPrefixes.Property) { if (node.Name == "Style") { styleLink = node["Style"].InnerText; } else { values.Add(node.LocalName, ParsingHelper.ParseValue(context, changeType, node)); } } else { if (type.GetInterface("SharpMedia.Graphics.GUI.Widgets.Containers.IContainer") == null) { throw new ParseException(string.Format("Only containers can have child widgets, " + "{0} is not a container.", name)); } Type resolveType = context.ResolveType(node.Prefix, node.LocalName); if (resolveType != null && resolveType.GetInterface("SharpMedia.Graphics.GUI.Widgets.IWidget") != null) { // We have a child element. ASTWidget widget = new ASTWidget(); children.Add(node.LocalName, widget); widget.Parse(context, node); } else { throw new ParseException("Only widgets are acceptable as children."); } } }
public void Parse(CompileContext context, System.Xml.XmlNode node) { XmlAttribute att = node.Attributes["Namespace"]; nsp = att.InnerText; att = node.Attributes["ContextName"]; if (att != null) { applicationContext = att.InnerText; } foreach (XmlNode child in node.ChildNodes) { if (child.NodeType != XmlNodeType.Element) { continue; } Type type = context.ResolveType(child.Prefix, child.LocalName); if (type != null && type.GetInterface("SharpMedia.Graphics.GUI.Widgets.IWidget") != null) { ASTWidget widget = new ASTWidget(); widget.Parse(context, child); children.Add(widget); } else if (type != null && type.GetInterface("SharpMedia.Graphics.GUI.IStateStyle") != null) { Styles.ASTStyle style = new Styles.ASTStyle(); style.Parse(context, child); children.Add(style); } else if (type != null && type.GetInterface("SharpMedia.Graphics.GUI.Animations.IAnimation") != null) { Animations.ASTAnimation animation = new Animations.ASTAnimation(type); animation.Parse(context, child); children.Add(animation); } else { throw new ParseException("Invalid type of not one of style/widget/animation."); } } context.ApplicationContextType = applicationContext; }
public void PreEmit(CompileContext context, System.IO.TextWriter writer) { name = context.GetNextTempName(); writer.WriteLine(" {0} {1} = new {0}();", type.FullName, name); for (int i = 0; i < properties.Count; i++) { // Pre-emit variable. if (properties.Values[i] is IPreEmittable) { (properties.Values[i] as IPreEmittable).PreEmit(context, writer); } // We write it and assign. writer.Write(" {0}.{1} = ", name, properties.Keys[i]); properties.Values[i].Emit(context, writer); writer.WriteLine(";"); } }
public void Parse(CompileContext context, System.Xml.XmlNode node) { ASTScalar width = null, height = null; if (node.Attributes["Width"] != null) { width = new ASTScalar(); width.Parse(context, Token.StackForm(Token.Tokenize(node.Attributes["Width"].InnerText))); } if (node.Attributes["X"] != null) { if (width != null) { throw new ParseException("Could not combine X and Width, same meaning in terms of vector."); } width = new ASTScalar(); width.Parse(context, Token.StackForm(Token.Tokenize(node.Attributes["X"].InnerText))); } if (node.Attributes["Height"] != null) { height = new ASTScalar(); height.Parse(context, Token.StackForm(Token.Tokenize(node.Attributes["Height"].InnerText))); } if (node.Attributes["Y"] != null) { if (height != null) { throw new ParseException("Could not combine Y and Height, same meaning in terms of vector."); } height = new ASTScalar(); height.Parse(context, Token.StackForm(Token.Tokenize(node.Attributes["Y"].InnerText))); } // Default to zero if (width == null) { width = new ASTScalar(); width.Scalar = new GuiScalar(0.0f); } if (height == null) { height = new ASTScalar(); height.Scalar = new GuiScalar(0.0f); } data = new GuiVector2(width.Scalar, height.Scalar); }
/// <summary> /// We parse value as text. /// </summary> public static IEmittable ParseValue(CompileContext context, Type changeType, string property, string value) { // We find the name in changeType. PropertyInfo info = changeType.GetProperty(property); if (info == null || !info.CanWrite) { throw new ParseException(string.Format("The property '{0}' for class '{1}' either does not exist" + " or it is not writable.", property, changeType.Name)); } Type type = info.PropertyType; if (type == typeof(GuiScalar)) { ASTScalar scalar = new ASTScalar(); scalar.Parse(context, Token.StackForm(Token.Tokenize(value))); return(scalar); } else if (type == typeof(GuiRect)) { ASTRect rect = new ASTRect(); rect.Parse(context, Token.StackForm(Token.Tokenize(value))); return(rect); } else if (type == typeof(GuiVector2)) { ASTVector2 v = new ASTVector2(); v.Parse(context, Token.StackForm(Token.Tokenize(value))); return(v); } else if (type == typeof(string)) { ASTString s = new ASTString(); s.Value = value; return(s); } else if (type == typeof(int)) { ASTInt s = new ASTInt(); s.Value = int.Parse(value, CultureInfo.InvariantCulture.NumberFormat); return(s); } else if (type == typeof(uint)) { ASTUInt s = new ASTUInt(); s.Value = uint.Parse(value, CultureInfo.InvariantCulture.NumberFormat); return(s); } else if (type == typeof(bool)) { ASTBool s = new ASTBool(); s.Value = bool.Parse(value); return(s); } else if (type.BaseType == typeof(Enum)) { ASTEnum e = new ASTEnum(type, value); return(e); } else if (type == typeof(Colour)) { ASTColour c = new ASTColour(); c.Parse(context, Token.StackForm(Token.Tokenize(value))); return(c); } else if (type.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(string) }, null) != null) { // We try with "Parse" method. ASTStringParsable p = new ASTStringParsable(value, type); return(p); } else { throw new ParseException(string.Format("The property {0} is not supported because it is not built-in or does not" + " implement a static Parse(string) method.", property)); } }
/// <summary> /// We parse the value as XmlNode. /// </summary> public static IEmittable ParseValue(CompileContext context, Type changeType, XmlNode node) { // We find the name in changeType. PropertyInfo info = changeType.GetProperty(node.LocalName); if (info == null || !info.CanWrite) { throw new ParseException(string.Format("The property '{0}' for class '{1}' either does not exist" + " or it is not writable.", node.Name, changeType)); } Type type = info.PropertyType; // A property defines a bucket, where internal is of different type. if (node.Prefix == StandardPrefixes.Property) { ASTXmlParsableProperty prop = new ASTXmlParsableProperty(type); prop.Parse(context, node); return(prop); } // A normal, direct initialization. if (type == typeof(GuiScalar)) { ASTScalar scalar = new ASTScalar(); scalar.Parse(context, node); return(scalar); } else if (type == typeof(GuiRect)) { ASTRect rect = new ASTRect(); rect.Parse(context, node); return(rect); } else if (type == typeof(GuiVector2)) { ASTVector2 v = new ASTVector2(); v.Parse(context, node); return(v); } else if (type == typeof(string)) { ASTString s = new ASTString(); s.Value = node.InnerText; return(s); } else { // If there is only a 'Value' tag with no children, we consider using normal parsing. if (node.Attributes.Count == 1 && node.Attributes["Value"] != null && node.ChildNodes.Count == 0) { return(ParseValue(context, changeType, node.LocalName, node.Value)); } // If no alternative, we use generic XMLParseable. ASTXmlParsable parseable = new ASTXmlParsable(type); parseable.Parse(context, node); return(parseable); } }
public void Emit(CompileContext context, System.IO.TextWriter writer) { writer.Write(name); }
public void Emit(CompileContext context, System.IO.TextWriter writer) { writer.WriteLine("{0}.Parse({1})", type, data); }
public void Emit(CompileContext context, System.IO.TextWriter writer) { writer.WriteLine(); writer.WriteLine(); writer.WriteLine(" /// <summary>"); writer.WriteLine(" /// Partial class {0}, based on {1}.", name, type.Name); writer.WriteLine(" /// </summary>"); writer.WriteLine(" public partial class {0} : {1} {{", name, type.FullName); writer.WriteLine(); writer.WriteLine(" #region Private Members"); writer.WriteLine(" {0} shareContext;", context.ApplicationContextType); writer.WriteLine(" #endregion"); writer.WriteLine(); writer.WriteLine(" #region Public Members"); writer.WriteLine(); writer.WriteLine(" /// <summary>"); writer.WriteLine(" /// Default constructor for {0}.", name); writer.WriteLine(" /// </summary>"); writer.WriteLine(" public {0}({1} shareContext) {{", name, context.ApplicationContextType); writer.WriteLine(" this.shareContext = shareContext;"); writer.WriteLine(" this.shareContext.{0} = this;", name); writer.WriteLine(); writer.WriteLine(" using({0} context = CreateChangeContextGeneral() as {0}) {{", changeType.FullName); // If style link. if (styleLink != null) { writer.WriteLine(" context.Style = shareContext.{0};", styleLink); } // We now initialize all values. for (int i = 0; i < values.Count; i++) { // We pre-emit. if (values.Values[i] is IPreEmittable) { (values.Values[i] as IPreEmittable).PreEmit(context, writer); } // We actually emit. if (!(values.Values[i] is IEmittable)) { continue; } writer.Write(" context.{0} = ", values.Keys[i]); (values.Values[i] as IEmittable).Emit(context, writer); writer.WriteLine(";"); } // We also add all children. for (int i = 0; i < children.Count; i++) { if (children.Values[i] is ASTWidget) { writer.WriteLine(" context.AddChild(new {0}(shareContext));", (children.Values[i] as ASTWidget).ClassName); } } writer.WriteLine(" }"); writer.WriteLine(" }"); writer.WriteLine(); writer.WriteLine(" #endregion"); writer.WriteLine(); writer.WriteLine(" }"); for (int i = 0; i < children.Count; i++) { if (children.Values[i] is IEmittable) { (children.Values[i] as IEmittable).Emit(context, writer); } } }
public void Parse(CompileContext context, Stack <Token> stream) { float pixel = 0.0f, parent = 0.0f, canvas = 0.0f; // We now parse until unknown token is found. Token token; while (true) { token = stream.Pop(); bool?sign = true; // May be '+' or '-'. if (token.TokenId == TokenId.Plus) { sign = true; token = stream.Pop(); } else if (token.TokenId == TokenId.Minus) { sign = false; token = stream.Pop(); } // We parse number. if (token.TokenId != TokenId.Number) { stream.Push(token); if (sign.HasValue) { throw new ParseException("Number expected after +/-"); } break; } float number = float.Parse(token.Identifier); string specifier = "p"; // We parse specifier token = stream.Pop(); // We also allow '%' elements, id specifier is empty. if (token.TokenId == TokenId.Percent) { if (token.TokenId == TokenId.Percent) { number *= 0.01f; } token = stream.Pop(); } else if (token.TokenId == TokenId.Identifier) { specifier = token.Identifier; token = stream.Pop(); } if (sign.HasValue) { number *= sign.Value ? 1.0f : -1.0f; } // We apply values. specifier = specifier.ToLower(); if (specifier == "p") { parent += number; } else if (specifier == "px") { pixel += number; } else if (specifier == "c") { canvas += number; } else { throw new ParseException("Scalar parsing failed: expected '', 'p', 'px' or 'c' specifier"); } stream.Push(token); // We now need '+', or we break it. if (token.TokenId != TokenId.Plus && token.TokenId != TokenId.Minus) { break; } // We do not pop it, part of stream. } data = new GuiScalar(pixel, canvas, parent); }
public void Parse(CompileContext context, System.Xml.XmlNode node) { XmlAttributeCollection attr = node.Attributes; ASTScalar left = null, right = null, top = null, bottom = null, width = null, height = null; if (attr["Left"] != null) { left = new ASTScalar(); left.Parse(context, Token.StackForm(Token.Tokenize(attr["Left"].InnerText))); } if (attr["Right"] != null) { right = new ASTScalar(); right.Parse(context, Token.StackForm(Token.Tokenize(attr["Right"].InnerText))); } if (attr["Top"] != null) { top = new ASTScalar(); top.Parse(context, Token.StackForm(Token.Tokenize(attr["Top"].InnerText))); } if (attr["Bottom"] != null) { bottom = new ASTScalar(); bottom.Parse(context, Token.StackForm(Token.Tokenize(attr["Bottom"].InnerText))); } if (attr["Width"] != null) { width = new ASTScalar(); width.Parse(context, Token.StackForm(Token.Tokenize(attr["Width"].InnerText))); } if (attr["Height"] != null) { height = new ASTScalar(); height.Parse(context, Token.StackForm(Token.Tokenize(attr["Height"].InnerText))); } // We now try combinations, must be defined somehow. We check four corners. if (left != null && right != null && top != null && bottom != null && height == null && width == null) { this.rectangle = new GuiRect(RectangleMode.MinMax, new GuiVector2(left.Scalar, bottom.Scalar), new GuiVector2(right.Scalar, top.Scalar)); return; } // We default width/height. if (width == null) { width = new ASTScalar(); width.Scalar = new GuiScalar(0.0f); } if (height == null) { height = new ASTScalar(); height.Scalar = new GuiScalar(0.0f); } // Now we check combinations. if (left != null && right == null && top == null && bottom != null) { this.rectangle = new GuiRect(RectangleMode.LeftBottomAndSize, new GuiVector2(left.Scalar, bottom.Scalar), new GuiVector2(width.Scalar, height.Scalar)); return; } if (left != null && right == null && top != null && bottom == null) { this.rectangle = new GuiRect(RectangleMode.LeftTopAndSize, new GuiVector2(left.Scalar, top.Scalar), new GuiVector2(width.Scalar, height.Scalar)); return; } if (left == null && right != null && top != null && bottom == null) { this.rectangle = new GuiRect(RectangleMode.RightTopAndSize, new GuiVector2(right.Scalar, top.Scalar), new GuiVector2(width.Scalar, height.Scalar)); return; } if (left == null && right != null && top == null && bottom != null) { this.rectangle = new GuiRect(RectangleMode.RightBottomAndSize, new GuiVector2(right.Scalar, bottom.Scalar), new GuiVector2(width.Scalar, height.Scalar)); return; } throw new ParseException("The rectangle is malformed."); }
public void Emit(CompileContext context, System.IO.TextWriter writer) { writer.Write(data.ToString(CultureInfo.InvariantCulture.NumberFormat)); }
public void Emit(CompileContext context, System.IO.TextWriter writer) { writer.Write("\"{0}\"", data); }
void ProcessAttribute(CompileContext context, XmlAttribute node) { values.Add(node.LocalName, ParsingHelper.ParseValue(context, changeType, node.LocalName, node.InnerText)); }
public void Emit(CompileContext context, System.IO.TextWriter writer) { writer.Write(ToString()); }
public void PreEmit(CompileContext context, System.IO.TextWriter writer) { inner.PreEmit(context, writer); }
public void Emit(CompileContext context, System.IO.TextWriter writer) { writer.Write(Common.LicenceInfoStringAsComment); writer.WriteLine("// This file was generated by GUI compiler from XML."); writer.WriteLine("// Do not change this file because it may be overriden by next build."); writer.WriteLine("namespace {0} {{", nsp); foreach (IElement child in children) { if (child is IEmittable && child is ASTWidget) { (child as IEmittable).Emit(context, writer); } } // We now create ApplicationContext. writer.WriteLine(); writer.WriteLine(); writer.WriteLine(" /// <summary>"); writer.WriteLine(" /// An {0}, the root manager class of GUI.", applicationContext); writer.WriteLine(" /// </summary>"); writer.WriteLine(" public class {0} {{", applicationContext); writer.WriteLine(); writer.WriteLine(" #region Private Members"); // All widgets. for (int i = 0; i < context.Widgets.Count; i++) { writer.WriteLine(" {0} widget{0} = null;", context.Widgets.Keys[i]); } // Named styles. for (int i = 0; i < context.Styles.Count; i++) { writer.WriteLine(" SharpMedia.Graphics.GUI.Style style{0} = null;", context.Styles.Keys[i]); } // Animations. for (int i = 0; i < context.Animations.Count; i++) { writer.WriteLine(" SharpMedia.Graphics.GUI.Animations.IAnimation animation{0} = null;", context.Animations.Keys[i]); } // Constructor. writer.WriteLine(); writer.WriteLine(" /// <summary"); writer.WriteLine(" /// Private constructor."); writer.WriteLine(" /// </summary"); writer.WriteLine(" private {0}() {{}}", applicationContext); writer.WriteLine(" #endregion"); writer.WriteLine(); writer.WriteLine(" #region Properties"); writer.WriteLine(); // The root widget. writer.WriteLine(); writer.WriteLine(" /// </summary>"); writer.WriteLine(" /// Gets the root widget"); writer.WriteLine(" /// </summary>"); writer.WriteLine(" public {0} Root", rootWidget.ClassName); writer.WriteLine(" {"); writer.WriteLine(" get"); writer.WriteLine(" {"); writer.WriteLine(" return widget{0};", rootWidget.ClassName); writer.WriteLine(" }"); writer.WriteLine(" }"); // All widgets. for (int i = 0; i < context.Widgets.Count; i++) { writer.WriteLine(); writer.WriteLine(" /// </summary>"); writer.WriteLine(" /// Gets the widget {0}", context.Widgets.Keys[i]); writer.WriteLine(" /// </summary>"); writer.WriteLine(" public {0} {0}", context.Widgets.Keys[i]); writer.WriteLine(" {"); writer.WriteLine(" get"); writer.WriteLine(" {"); writer.WriteLine(" return widget{0};", context.Widgets.Keys[i]); writer.WriteLine(" }"); writer.WriteLine(" internal set"); writer.WriteLine(" {"); writer.WriteLine(" if(widget{0} != null) throw new System.ArgumentException(\"Cannot re-set variable.\");", context.Widgets.Keys[i]); writer.WriteLine(" widget{0} = value;", context.Widgets.Keys[i]); writer.WriteLine(" }"); writer.WriteLine(" }"); } // All styles. for (int i = 0; i < context.Styles.Count; i++) { writer.WriteLine(); writer.WriteLine(" /// <summary>"); writer.WriteLine(" /// Gets the style {0}.", context.Styles.Keys[i]); writer.WriteLine(" /// </summary"); writer.WriteLine(" public SharpMedia.Graphics.GUI.Style {0}", context.Styles.Keys[i]); writer.WriteLine(" {"); writer.WriteLine(" get"); writer.WriteLine(" {"); writer.WriteLine(" return style{0};", context.Styles.Keys[i]); writer.WriteLine(" }"); writer.WriteLine(" }"); } // All animations. for (int i = 0; i < context.Animations.Count; i++) { writer.WriteLine(); writer.WriteLine(" /// <summary>"); writer.WriteLine(" /// Gets the animation {0}.", context.Animations.Keys[i]); writer.WriteLine(" /// </summary"); writer.WriteLine(" public SharpMedia.Graphics.GUI.Animations.IAnimation {0}", context.Animations.Keys[i]); writer.WriteLine(" {"); writer.WriteLine(" get"); writer.WriteLine(" {"); writer.WriteLine(" return animation{0};", context.Animations.Keys[i]); writer.WriteLine(" }"); writer.WriteLine(" }"); } writer.WriteLine(" #endregion"); writer.WriteLine(); writer.WriteLine(" #region Public Members"); writer.WriteLine(); writer.WriteLine(" public static {0} CreateApplication(SharpMedia.Graphics.GUI.Themes.IGuiTheme theme)", context.ApplicationContextType); writer.WriteLine(" {"); writer.WriteLine(" // We first create context."); writer.WriteLine(" {0} context = new {0}();", context.ApplicationContextType); writer.WriteLine(); writer.WriteLine(" // We first apply all styles."); // We apply all styles. for (int i = 0; i < context.Styles.Count; i++) { context.Styles.Values[i].PreEmit(context, writer); writer.Write(" context.style{0} = ", context.Styles.Keys[i]); context.Styles.Values[i].Emit(context, writer); writer.WriteLine(";"); } // We now apply all animations. for (int i = 0; i < context.Animations.Count; i++) { context.Animations.Values[i].PreEmit(context, writer); writer.WriteLine(" context.animation{0} = ", context.Animations.Keys[i]); context.Animations.Values[i].Emit(context, writer); } // At last, we set the root. writer.WriteLine(); writer.WriteLine(" // We create root, createing all children."); writer.WriteLine(" new {0}(context);", rootWidget.ClassName); // We also apply theme. writer.WriteLine(" if(theme != null) theme.AutomaticApply(context.Root, true);"); writer.WriteLine(" return context;"); writer.WriteLine(" }"); writer.WriteLine(); writer.WriteLine(" #endregion"); writer.WriteLine(); writer.WriteLine(" }"); writer.WriteLine("}"); }
public void Parse(CompileContext context, Stack <Token> stream) { // We have following parsing: // [Type:]GuiVector2, GuiVector2 // where Type = MinMax | LeftBottomAndSize | RightBottomAndSize | LeftTopAndSize | RightTopAndSize // We first check for type. Token token = stream.Pop(); RectangleMode mode = RectangleMode.MinMax; if (token.TokenId == TokenId.Identifier) { string id = token.Identifier; switch (id.ToLower()) { case "minmax": mode = RectangleMode.MinMax; break; case "leftbottomandsize": mode = RectangleMode.LeftBottomAndSize; break; case "rightbottomandsize": mode = RectangleMode.RightBottomAndSize; break; case "lefttopandsize": mode = RectangleMode.LeftTopAndSize; break; case "righttopandsize": mode = RectangleMode.RightTopAndSize; break; default: stream.Push(token); throw new ParseException("Expected a valid type identifier for rectangle."); } token = stream.Pop(); if (token.TokenId != TokenId.Colon) { stream.Push(token); throw new ParseException("If specifier for rectangle is used, it must be followed by ':'."); } token = stream.Pop(); } stream.Push(token); ASTVector2 v1 = new ASTVector2(), v2 = new ASTVector2(); v1.Parse(context, stream); token = stream.Pop(); if (token.TokenId != TokenId.Comma) { stream.Push(token); throw new ParseException("Comma expected to seperate vectors in rectangle."); } v2.Parse(context, stream); // We now apply data. rectangle = new GuiRect(mode, v1.Vector, v2.Vector); }