diff --git a/OpenRA.FileFormats/Evaluator.cs b/OpenRA.FileFormats/Evaluator.cs index 95b5d435ea..c48834956f 100644 --- a/OpenRA.FileFormats/Evaluator.cs +++ b/OpenRA.FileFormats/Evaluator.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; @@ -29,7 +29,6 @@ namespace OpenRA.FileFormats default: s.Push(int.Parse(t)); break; } } - return s.Pop(); } @@ -43,7 +42,6 @@ namespace OpenRA.FileFormats static IEnumerable ToPostfix(IEnumerable toks, Dictionary syms) { var s = new Stack(); - foreach (var t in toks) { if (t[0] == '(') s.Push(t); @@ -53,14 +51,20 @@ namespace OpenRA.FileFormats while ((temp = s.Pop()) != "(") yield return temp; } else if (char.IsNumber(t[0])) yield return t; - else if (char.IsLetter(t[0])) yield return syms[t].ToString(); + 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(); } diff --git a/OpenRA.Game/Chrome.cs b/OpenRA.Game/Chrome.cs index 8840428d5e..7bcebc7d44 100644 --- a/OpenRA.Game/Chrome.cs +++ b/OpenRA.Game/Chrome.cs @@ -134,6 +134,7 @@ namespace OpenRA // Hack around a bug in MiniYaml widgetYaml.Values.FirstOrDefault().Value = widgetYaml.Keys.FirstOrDefault(); WidgetLoader.rootWidget = WidgetLoader.LoadWidget(widgetYaml.Values.FirstOrDefault()); + WidgetLoader.rootWidget.Initialize(); } List visibleTabs = new List(); diff --git a/OpenRA.Game/Chrome/Widget.cs b/OpenRA.Game/Chrome/Widget.cs index d871e45dd7..26e073147c 100644 --- a/OpenRA.Game/Chrome/Widget.cs +++ b/OpenRA.Game/Chrome/Widget.cs @@ -23,44 +23,66 @@ namespace OpenRA.Widgets // Calculated internally public Rectangle Bounds; - public Rectangle ClickRect; + public Rectangle EventBounds; + public Widget Parent = null; public virtual void Initialize() { + Log.Write("{0} has parent {1}", Id, Parent == null ? "NULL" : Parent.Id); + // Evaluate the bounds rectangle - Bounds = new Rectangle(int.Parse(X),int.Parse(Y),int.Parse(Width),int.Parse(Height)); - + Rectangle parentBounds = (Parent == null) ? new Rectangle(0,0,Game.viewport.Width,Game.viewport.Height) : Parent.Bounds; + + Dictionary substitutions = new Dictionary(); + substitutions.Add("WINDOW_RIGHT", Game.viewport.Width); + substitutions.Add("WINDOW_BOTTOM", Game.viewport.Height); + substitutions.Add("PARENT_RIGHT", parentBounds.Width); + substitutions.Add("PARENT_BOTTOM", parentBounds.Height); + int width = Evaluator.Evaluate(Width, substitutions); + int height = Evaluator.Evaluate(Height, substitutions); + + substitutions.Add("WIDTH", width); + substitutions.Add("HEIGHT", height); + + Bounds = new Rectangle(parentBounds.X + Evaluator.Evaluate(X, substitutions), + parentBounds.Y + Evaluator.Evaluate(Y, substitutions), + width, + height); // Create the clickrect - ClickRect = Bounds; + EventBounds = Bounds; foreach (var child in Children) - ClickRect = Rectangle.Union(ClickRect, child.Bounds); + { + child.Initialize(); + EventBounds = Rectangle.Union(EventBounds, child.Bounds); + } } + public virtual void UpdateEventBounds() + { + EventBounds = Bounds; + foreach (var child in Children) + EventBounds = Rectangle.Union(EventBounds, child.Bounds); + + Parent.UpdateEventBounds(); + } + public virtual bool HandleInput(MouseInput mi) { - if (!Visible) + // Are we able to handle this event? + if (!Visible || !EventBounds.Contains(mi.Location.X,mi.Location.Y)) return false; - // Do any of our children handle this? - bool caught = false; - if (ClickRect.Contains(mi.Location.X,mi.Location.Y)) + // Can any of our children handle this? + foreach (var child in Children) { - foreach (var child in Children) - { - caught = child.HandleInput(mi); - if (caught) - break; - } + if (child.HandleInput(mi)) + return true; } - - // Child has handled the event - if (caught) - return true; - + // Mousedown - if (Delegate != null && mi.Event == MouseInputEvent.Down && ClickRect.Contains(mi.Location.X,mi.Location.Y)) + if (Delegate != null && mi.Event == MouseInputEvent.Down) { foreach (var mod in Game.ModAssemblies) { @@ -84,6 +106,9 @@ namespace OpenRA.Widgets public void AddChild(Widget child) { + child.Parent = this; + Log.Write("{0} setting parent {1}", child.Id, Id); + Children.Add( child ); } diff --git a/OpenRA.Game/Chrome/WidgetLoader.cs b/OpenRA.Game/Chrome/WidgetLoader.cs index 259131ccad..feb2a05414 100644 --- a/OpenRA.Game/Chrome/WidgetLoader.cs +++ b/OpenRA.Game/Chrome/WidgetLoader.cs @@ -30,10 +30,9 @@ namespace OpenRA else FieldLoader.LoadField( widget, child.Key, child.Value ); } - widget.Initialize(); return widget; } - + static Widget NewWidget( string widgetType ) { if( widgetType.Contains( "@" ) ) diff --git a/mods/cnc/menus.yaml b/mods/cnc/menus.yaml index f41e9d772c..a8aab4b16a 100644 --- a/mods/cnc/menus.yaml +++ b/mods/cnc/menus.yaml @@ -2,39 +2,39 @@ Container: Children: Background@MAINMENU_BG: Id:MAINMENU_BG - X:400 + X:WINDOW_RIGHT/2 - 125 Y:200 Width:250 Height:200 Children: - Label@MAINMENDelegateU_LABEL_TITLE: + Label@MAINMENU_LABEL_TITLE: Id:MAINMENU_LABEL_TITLE - X:445 - Y:220 - Width:160 + X:0 + Y:20 + Width:250 Height:25 Text:OpenRA Main Menu Align:Center Button@MAINMENU_BUTTON_JOIN: Id:MAINMENU_BUTTON_JOIN - X:445 - Y:270 + X:45 + Y:70 Width:160 Height:25 Text:Join Game Delegate:MainMenuButtonsDelegate Button@MAINMENU_BUTTON_CREATE: Id:MAINMENU_BUTTON_CREATE - X:445 - Y:305 + X:45 + Y:110 Width:160 Height:25 Text:Create Game Delegate:MainMenuButtonsDelegate Button@MAINMENU_BUTTON_QUIT: Id:MAINMENU_BUTTON_QUIT - X:445 - Y:340 + X:45 + Y:150 Width:160 Height:25 Text:Quit @@ -49,37 +49,37 @@ Container: Children: Label@CREATESERVER_LABEL_TITLE: Id:CREATESERVER_LABEL_TITLE - X:445 - Y:220 - Width:160 + X:0 + Y:20 + Width:250 Height:25 Text:Create Server Align:Center Button@CREATESERVER_CHECKBOX_HIDDEN: Id:CREATESERVER_CHECKBOX_HIDDEN - X:400 - Y:260 + X:100 + Y:60 Width:20 Height:20 Label@CREATESERVER_LABEL_HIDDENGAME: Id:CREATESERVER_LABEL_HIDDENGAME - X:435 - Y:260 + X:135 + Y:60 Width:300 Height:25 Text:Hide from Server Browser Button@CREATESERVER_BUTTON_CANCEL: Id:CREATESERVER_BUTTON_CANCEL - X:400 - Y:300 + X:100 + Y:100 Width:160 Height:25 Text:Cancel Delegate:MainMenuButtonsDelegate Button@CREATESERVER_BUTTON_START: Id:CREATESERVER_BUTTON_START - X:570 - Y:300 + X:270 + Y:100 Width:160 Height:25 Text:Create