Use Evaluator for positioning; Refactoring; Position elements relative to parents; Broke clicks outside of parent rect

This commit is contained in:
Paul Chote
2010-03-15 19:56:29 +13:00
parent 9ecb0d57f1
commit b70420e373
5 changed files with 79 additions and 50 deletions

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -29,7 +29,6 @@ namespace OpenRA.FileFormats
default: s.Push(int.Parse(t)); break; default: s.Push(int.Parse(t)); break;
} }
} }
return s.Pop(); return s.Pop();
} }
@@ -43,7 +42,6 @@ namespace OpenRA.FileFormats
static IEnumerable<string> ToPostfix(IEnumerable<string> toks, Dictionary<string, int> syms) static IEnumerable<string> ToPostfix(IEnumerable<string> toks, Dictionary<string, int> syms)
{ {
var s = new Stack<string>(); var s = new Stack<string>();
foreach (var t in toks) foreach (var t in toks)
{ {
if (t[0] == '(') s.Push(t); if (t[0] == '(') s.Push(t);
@@ -53,14 +51,20 @@ namespace OpenRA.FileFormats
while ((temp = s.Pop()) != "(") yield return temp; while ((temp = s.Pop()) != "(") yield return temp;
} }
else if (char.IsNumber(t[0])) yield return t; 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 else
{ {
while (s.Count > 0 && Prec[t] <= Prec[s.Peek()]) yield return s.Pop(); while (s.Count > 0 && Prec[t] <= Prec[s.Peek()]) yield return s.Pop();
s.Push(t); s.Push(t);
} }
} }
while (s.Count > 0) yield return s.Pop(); while (s.Count > 0) yield return s.Pop();
} }

View File

@@ -134,6 +134,7 @@ namespace OpenRA
// Hack around a bug in MiniYaml // Hack around a bug in MiniYaml
widgetYaml.Values.FirstOrDefault().Value = widgetYaml.Keys.FirstOrDefault(); widgetYaml.Values.FirstOrDefault().Value = widgetYaml.Keys.FirstOrDefault();
WidgetLoader.rootWidget = WidgetLoader.LoadWidget(widgetYaml.Values.FirstOrDefault()); WidgetLoader.rootWidget = WidgetLoader.LoadWidget(widgetYaml.Values.FirstOrDefault());
WidgetLoader.rootWidget.Initialize();
} }
List<string> visibleTabs = new List<string>(); List<string> visibleTabs = new List<string>();

View File

@@ -23,44 +23,66 @@ namespace OpenRA.Widgets
// Calculated internally // Calculated internally
public Rectangle Bounds; public Rectangle Bounds;
public Rectangle ClickRect; public Rectangle EventBounds;
public Widget Parent = null;
public virtual void Initialize() public virtual void Initialize()
{ {
Log.Write("{0} has parent {1}", Id, Parent == null ? "NULL" : Parent.Id);
// Evaluate the bounds rectangle // 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<string, int> substitutions = new Dictionary<string, int>();
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 // Create the clickrect
ClickRect = Bounds; EventBounds = Bounds;
foreach (var child in Children) 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) 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; return false;
// Do any of our children handle this? // Can any of our children handle this?
bool caught = false; foreach (var child in Children)
if (ClickRect.Contains(mi.Location.X,mi.Location.Y))
{ {
foreach (var child in Children) if (child.HandleInput(mi))
{ return true;
caught = child.HandleInput(mi);
if (caught)
break;
}
} }
// Child has handled the event
if (caught)
return true;
// Mousedown // 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) foreach (var mod in Game.ModAssemblies)
{ {
@@ -84,6 +106,9 @@ namespace OpenRA.Widgets
public void AddChild(Widget child) public void AddChild(Widget child)
{ {
child.Parent = this;
Log.Write("{0} setting parent {1}", child.Id, Id);
Children.Add( child ); Children.Add( child );
} }

View File

@@ -30,10 +30,9 @@ namespace OpenRA
else else
FieldLoader.LoadField( widget, child.Key, child.Value ); FieldLoader.LoadField( widget, child.Key, child.Value );
} }
widget.Initialize();
return widget; return widget;
} }
static Widget NewWidget( string widgetType ) static Widget NewWidget( string widgetType )
{ {
if( widgetType.Contains( "@" ) ) if( widgetType.Contains( "@" ) )

View File

@@ -2,39 +2,39 @@ Container:
Children: Children:
Background@MAINMENU_BG: Background@MAINMENU_BG:
Id:MAINMENU_BG Id:MAINMENU_BG
X:400 X:WINDOW_RIGHT/2 - 125
Y:200 Y:200
Width:250 Width:250
Height:200 Height:200
Children: Children:
Label@MAINMENDelegateU_LABEL_TITLE: Label@MAINMENU_LABEL_TITLE:
Id:MAINMENU_LABEL_TITLE Id:MAINMENU_LABEL_TITLE
X:445 X:0
Y:220 Y:20
Width:160 Width:250
Height:25 Height:25
Text:OpenRA Main Menu Text:OpenRA Main Menu
Align:Center Align:Center
Button@MAINMENU_BUTTON_JOIN: Button@MAINMENU_BUTTON_JOIN:
Id:MAINMENU_BUTTON_JOIN Id:MAINMENU_BUTTON_JOIN
X:445 X:45
Y:270 Y:70
Width:160 Width:160
Height:25 Height:25
Text:Join Game Text:Join Game
Delegate:MainMenuButtonsDelegate Delegate:MainMenuButtonsDelegate
Button@MAINMENU_BUTTON_CREATE: Button@MAINMENU_BUTTON_CREATE:
Id:MAINMENU_BUTTON_CREATE Id:MAINMENU_BUTTON_CREATE
X:445 X:45
Y:305 Y:110
Width:160 Width:160
Height:25 Height:25
Text:Create Game Text:Create Game
Delegate:MainMenuButtonsDelegate Delegate:MainMenuButtonsDelegate
Button@MAINMENU_BUTTON_QUIT: Button@MAINMENU_BUTTON_QUIT:
Id:MAINMENU_BUTTON_QUIT Id:MAINMENU_BUTTON_QUIT
X:445 X:45
Y:340 Y:150
Width:160 Width:160
Height:25 Height:25
Text:Quit Text:Quit
@@ -49,37 +49,37 @@ Container:
Children: Children:
Label@CREATESERVER_LABEL_TITLE: Label@CREATESERVER_LABEL_TITLE:
Id:CREATESERVER_LABEL_TITLE Id:CREATESERVER_LABEL_TITLE
X:445 X:0
Y:220 Y:20
Width:160 Width:250
Height:25 Height:25
Text:Create Server Text:Create Server
Align:Center Align:Center
Button@CREATESERVER_CHECKBOX_HIDDEN: Button@CREATESERVER_CHECKBOX_HIDDEN:
Id:CREATESERVER_CHECKBOX_HIDDEN Id:CREATESERVER_CHECKBOX_HIDDEN
X:400 X:100
Y:260 Y:60
Width:20 Width:20
Height:20 Height:20
Label@CREATESERVER_LABEL_HIDDENGAME: Label@CREATESERVER_LABEL_HIDDENGAME:
Id:CREATESERVER_LABEL_HIDDENGAME Id:CREATESERVER_LABEL_HIDDENGAME
X:435 X:135
Y:260 Y:60
Width:300 Width:300
Height:25 Height:25
Text:Hide from Server Browser Text:Hide from Server Browser
Button@CREATESERVER_BUTTON_CANCEL: Button@CREATESERVER_BUTTON_CANCEL:
Id:CREATESERVER_BUTTON_CANCEL Id:CREATESERVER_BUTTON_CANCEL
X:400 X:100
Y:300 Y:100
Width:160 Width:160
Height:25 Height:25
Text:Cancel Text:Cancel
Delegate:MainMenuButtonsDelegate Delegate:MainMenuButtonsDelegate
Button@CREATESERVER_BUTTON_START: Button@CREATESERVER_BUTTON_START:
Id:CREATESERVER_BUTTON_START Id:CREATESERVER_BUTTON_START
X:570 X:270
Y:300 Y:100
Width:160 Width:160
Height:25 Height:25
Text:Create Text:Create