diff --git a/OpenRA.Game/GameRules/ActorInfo.cs b/OpenRA.Game/GameRules/ActorInfo.cs index 63bd3fda48..39c0065c18 100644 --- a/OpenRA.Game/GameRules/ActorInfo.cs +++ b/OpenRA.Game/GameRules/ActorInfo.cs @@ -39,9 +39,10 @@ namespace OpenRA return null; MiniYaml parent; - allUnits.TryGetValue( inherits.Value, out parent ); - if( parent == null ) - return null; + allUnits.TryGetValue( inherits.Value, out parent ); + if (parent == null) + throw new InvalidOperationException( + "Bogus inheritance -- actor type {0} does not exist".F(inherits.Value)); return parent; } diff --git a/OpenRA.Game/Widgets/Widget.cs b/OpenRA.Game/Widgets/Widget.cs index 0ae6616be3..306326ed74 100644 --- a/OpenRA.Game/Widgets/Widget.cs +++ b/OpenRA.Game/Widgets/Widget.cs @@ -13,356 +13,369 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using OpenRA.FileFormats; -using OpenRA.Graphics; - -namespace OpenRA.Widgets -{ - public abstract class Widget - { - // 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 string Delegate = null; - public string EventHandler = null; - public bool Visible = true; - - public readonly List Children = new List(); - - // Calculated internally - public Rectangle Bounds; - public Widget Parent = null; - - public static Stack WindowList = new Stack(); - - // Common Funcs that most widgets will want - public Func OnMouseDown = mi => false; - public Func OnMouseUp = mi => false; - public Action OnMouseMove = mi => {}; - public Func OnKeyPress = e => false; - - public Func IsVisible; - - public Widget() { IsVisible = () => Visible; } - - public static Widget RootWidget - { - get { return rootWidget; } - set { rootWidget = value; } - } - private static Widget rootWidget = new ContainerWidget(); - - public Widget(Widget widget) - { - Id = widget.Id; - X = widget.X; - Y = widget.Y; - Width = widget.Width; - Height = widget.Height; - Delegate = widget.Delegate; - Visible = widget.Visible; - - Bounds = widget.Bounds; - Parent = widget.Parent; - - OnMouseDown = widget.OnMouseDown; - OnMouseUp = widget.OnMouseUp; - OnMouseMove = widget.OnMouseMove; - OnKeyPress = widget.OnKeyPress; - - IsVisible = widget.IsVisible; - - foreach(var child in widget.Children) - AddChild(child.Clone()); - } - - public virtual Widget Clone() - { - throw new InvalidOperationException("Widget type `{0}` is not cloneable.".F(GetType().Name)); - } - - public virtual int2 RenderOrigin - { - get - { - var offset = (Parent == null) ? int2.Zero : Parent.ChildOrigin; - return new int2(Bounds.X, Bounds.Y) + offset; - } - } - - public virtual int2 ChildOrigin { get { return RenderOrigin; } } - public virtual Rectangle RenderBounds { get { return new Rectangle(RenderOrigin.X, RenderOrigin.Y, Bounds.Width, Bounds.Height); } } - - public virtual void Initialize() - { - // Parse the YAML equations to find the widget bounds - var parentBounds = (Parent == null) - ? new Rectangle(0, 0, Game.viewport.Width, Game.viewport.Height) - : Parent.Bounds; - - var 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_LEFT", parentBounds.Left); - substitutions.Add("PARENT_TOP", parentBounds.Top); - 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(Evaluator.Evaluate(X, substitutions), - Evaluator.Evaluate(Y, substitutions), - width, - height); - } - - public void PostInit(Dictionary args) - { - if( Delegate != null ) - { - args["widget"] = this; - Game.modData.ObjectCreator.CreateObject(Delegate, args); - args.Remove("widget"); - } - } - - public virtual Rectangle EventBounds { get { return RenderBounds; } } - public virtual Rectangle GetEventBounds() - { - return Children - .Where(c => c.IsVisible()) - .Select(c => c.GetEventBounds()) - .Aggregate(EventBounds, Rectangle.Union); - } - - public static Widget SelectedWidget; - public bool Focused { get { return SelectedWidget == this; } } - public virtual bool TakeFocus(MouseInput mi) - { - if (Focused) - return true; - - if (SelectedWidget != null && !SelectedWidget.LoseFocus(mi)) - return false; - SelectedWidget = this; - return true; - } - - // Remove focus from this widget; return false if you don't want to give it up - public virtual bool LoseFocus(MouseInput mi) - { - // Some widgets may need to override focus depending on mouse click - return LoseFocus(); - } - - public virtual bool LoseFocus() - { - if (SelectedWidget == this) - SelectedWidget = null; - - return true; - } - - public virtual string GetCursor(int2 pos) { return "default"; } - public string GetCursorOuter(int2 pos) - { - // Is the cursor on top of us? - if (!(IsVisible() && GetEventBounds().Contains(pos))) - return null; - - // Do any of our children specify a cursor? - foreach (var child in Children.OfType().Reverse()) - { - var cc = child.GetCursorOuter(pos); - if (cc != null) - return cc; - } - - return EventBounds.Contains(pos) ? GetCursor(pos) : null; - } - - public static bool HandleInput(MouseInput mi) - { - bool handled = false; - if (SelectedWidget != null && SelectedWidget.HandleMouseInputOuter(mi)) - handled = true; - - if (!handled && RootWidget.HandleMouseInputOuter(mi)) - handled = true; - - if (mi.Event == MouseInputEvent.Move) - { - Viewport.LastMousePos = mi.Location; - Viewport.TicksSinceLastMove = 0; - } - return handled; - } - - public bool HandleMouseInputOuter(MouseInput mi) - { - // Are we able to handle this event? - if (!(Focused || (IsVisible() && GetEventBounds().Contains(mi.Location.X,mi.Location.Y)))) - return false; - - // Send the event to the deepest children first and bubble up if unhandled - foreach (var child in Children.OfType().Reverse()) - if (child.HandleMouseInputOuter(mi)) - return true; - - return HandleMouseInput(mi); - } - - // Hack: Don't eat mouse input that others want - // TODO: Solve this properly - public virtual bool HandleMouseInput(MouseInput mi) - { - // Apply any special logic added by delegates; they return true if they caught the input - if (mi.Event == MouseInputEvent.Down && OnMouseDown(mi)) return true; - if (mi.Event == MouseInputEvent.Up && OnMouseUp(mi)) return true; - if (mi.Event == MouseInputEvent.Move) - OnMouseMove(mi); - - return false; - } - - public virtual bool HandleKeyPressInner(KeyInput e) { return false; } - public virtual bool HandleKeyPressOuter(KeyInput e) - { - if (!IsVisible()) - return false; - - // Can any of our children handle this? - foreach (var child in Children) - if (child.HandleKeyPressOuter(e)) - return true; - - // Do any widgety behavior (enter text etc) - var handled = HandleKeyPressInner(e); - - // Apply any special logic added by delegates; they return true if they caught the input - if (OnKeyPress(e)) return true; - - return handled; - } - - public static bool HandleKeyPress(KeyInput e) - { - if (SelectedWidget != null) - return SelectedWidget.HandleKeyPressOuter(e); - - if (RootWidget.HandleKeyPressOuter(e)) - return true; - return false; - } - - public abstract void DrawInner(); - - public virtual void Draw() - { - if (IsVisible()) - { - DrawInner(); - foreach (var child in Children) - child.Draw(); - } - } - - public virtual void Tick() - { - if (IsVisible()) - foreach (var child in Children) - child.Tick(); - } - - public virtual void AddChild(Widget child) - { - child.Parent = this; - Children.Add( child ); - } - public virtual void RemoveChild(Widget child) { Children.Remove(child); } - public virtual void RemoveChildren() { Children.Clear(); } - - public Widget GetWidget(string id) - { - if (this.Id == id) - return this; - - foreach (var child in Children) - { - var w = child.GetWidget(id); - if (w != null) - return w; - } - return null; - } - - public T GetWidget(string id) where T : Widget - { - var widget = GetWidget(id); - return (widget != null)? (T) widget : null; - } - - public static void CloseWindow() - { - RootWidget.Children.Remove( WindowList.Pop() ); - if( WindowList.Count > 0 ) - rootWidget.Children.Add( WindowList.Peek() ); - } - - public static Widget OpenWindow( string id ) - { - return OpenWindow( id, new Dictionary() ); - } - - public static Widget OpenWindow(string id, Dictionary args ) - { - var window = Game.modData.WidgetLoader.LoadWidget( args, rootWidget, id ); - if( WindowList.Count > 0 ) - rootWidget.Children.Remove( WindowList.Peek() ); - WindowList.Push( window ); - return window; - } - - public static void DoTick() - { - RootWidget.Tick(); - } - - public static void DoDraw() - { - RootWidget.Draw(); - } - } - - public class ContainerWidget : Widget { - public Func GetBackground; - public string Background = null; - - public ContainerWidget() : base() - { - GetBackground = () => Background; - } - - public ContainerWidget(ContainerWidget other) : base(other) - { - Background = other.Background; - GetBackground = other.GetBackground; - } - - public override void DrawInner() - { - var bg = GetBackground(); - if (bg != null) - WidgetUtils.DrawPanel(bg, RenderBounds ); - } - - public override string GetCursor(int2 pos) { return null; } - public override Widget Clone() { return new ContainerWidget(this); } - } - public interface IWidgetDelegate { } +using OpenRA.Graphics; + +namespace OpenRA.Widgets +{ + public abstract class Widget + { + // 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 string Delegate = null; + public string EventHandler = null; + public bool Visible = true; + + public readonly List Children = new List(); + + // Calculated internally + public Rectangle Bounds; + public Widget Parent = null; + + public static Stack WindowList = new Stack(); + + // Common Funcs that most widgets will want + public Func OnMouseDown = mi => false; + public Func OnMouseUp = mi => false; + public Action OnMouseMove = mi => { }; + public Func OnKeyPress = e => false; + + public Func IsVisible; + + public Widget() { IsVisible = () => Visible; } + + public static Widget RootWidget + { + get { return rootWidget; } + set { rootWidget = value; } + } + private static Widget rootWidget = new ContainerWidget(); + + public Widget(Widget widget) + { + Id = widget.Id; + X = widget.X; + Y = widget.Y; + Width = widget.Width; + Height = widget.Height; + Delegate = widget.Delegate; + Visible = widget.Visible; + + Bounds = widget.Bounds; + Parent = widget.Parent; + + OnMouseDown = widget.OnMouseDown; + OnMouseUp = widget.OnMouseUp; + OnMouseMove = widget.OnMouseMove; + OnKeyPress = widget.OnKeyPress; + + IsVisible = widget.IsVisible; + + foreach (var child in widget.Children) + AddChild(child.Clone()); + } + + public virtual Widget Clone() + { + throw new InvalidOperationException("Widget type `{0}` is not cloneable.".F(GetType().Name)); + } + + public virtual int2 RenderOrigin + { + get + { + var offset = (Parent == null) ? int2.Zero : Parent.ChildOrigin; + return new int2(Bounds.X, Bounds.Y) + offset; + } + } + + public virtual int2 ChildOrigin { get { return RenderOrigin; } } + public virtual Rectangle RenderBounds { get { return new Rectangle(RenderOrigin.X, RenderOrigin.Y, Bounds.Width, Bounds.Height); } } + + public virtual void Initialize() + { + // Parse the YAML equations to find the widget bounds + var parentBounds = (Parent == null) + ? new Rectangle(0, 0, Game.viewport.Width, Game.viewport.Height) + : Parent.Bounds; + + var 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_LEFT", parentBounds.Left); + substitutions.Add("PARENT_TOP", parentBounds.Top); + 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(Evaluator.Evaluate(X, substitutions), + Evaluator.Evaluate(Y, substitutions), + width, + height); + } + + public void PostInit(Dictionary args) + { + if (Delegate == null) + return; + + args["widget"] = this; + + var iwd = Game.modData.ObjectCreator.CreateObject(Delegate, args) + as IWidgetDelegateEx; + if (iwd != null) + iwd.Init(); + + args.Remove("widget"); + } + + public virtual Rectangle EventBounds { get { return RenderBounds; } } + public virtual Rectangle GetEventBounds() + { + return Children + .Where(c => c.IsVisible()) + .Select(c => c.GetEventBounds()) + .Aggregate(EventBounds, Rectangle.Union); + } + + public static Widget SelectedWidget; + public bool Focused { get { return SelectedWidget == this; } } + public virtual bool TakeFocus(MouseInput mi) + { + if (Focused) + return true; + + if (SelectedWidget != null && !SelectedWidget.LoseFocus(mi)) + return false; + SelectedWidget = this; + return true; + } + + // Remove focus from this widget; return false if you don't want to give it up + public virtual bool LoseFocus(MouseInput mi) + { + // Some widgets may need to override focus depending on mouse click + return LoseFocus(); + } + + public virtual bool LoseFocus() + { + if (SelectedWidget == this) + SelectedWidget = null; + + return true; + } + + public virtual string GetCursor(int2 pos) { return "default"; } + public string GetCursorOuter(int2 pos) + { + // Is the cursor on top of us? + if (!(IsVisible() && GetEventBounds().Contains(pos))) + return null; + + // Do any of our children specify a cursor? + foreach (var child in Children.OfType().Reverse()) + { + var cc = child.GetCursorOuter(pos); + if (cc != null) + return cc; + } + + return EventBounds.Contains(pos) ? GetCursor(pos) : null; + } + + public static bool HandleInput(MouseInput mi) + { + bool handled = false; + if (SelectedWidget != null && SelectedWidget.HandleMouseInputOuter(mi)) + handled = true; + + if (!handled && RootWidget.HandleMouseInputOuter(mi)) + handled = true; + + if (mi.Event == MouseInputEvent.Move) + { + Viewport.LastMousePos = mi.Location; + Viewport.TicksSinceLastMove = 0; + } + return handled; + } + + public bool HandleMouseInputOuter(MouseInput mi) + { + // Are we able to handle this event? + if (!(Focused || (IsVisible() && GetEventBounds().Contains(mi.Location.X, mi.Location.Y)))) + return false; + + // Send the event to the deepest children first and bubble up if unhandled + foreach (var child in Children.OfType().Reverse()) + if (child.HandleMouseInputOuter(mi)) + return true; + + return HandleMouseInput(mi); + } + + // Hack: Don't eat mouse input that others want + // TODO: Solve this properly + public virtual bool HandleMouseInput(MouseInput mi) + { + // Apply any special logic added by delegates; they return true if they caught the input + if (mi.Event == MouseInputEvent.Down && OnMouseDown(mi)) return true; + if (mi.Event == MouseInputEvent.Up && OnMouseUp(mi)) return true; + if (mi.Event == MouseInputEvent.Move) + OnMouseMove(mi); + + return false; + } + + public virtual bool HandleKeyPressInner(KeyInput e) { return false; } + public virtual bool HandleKeyPressOuter(KeyInput e) + { + if (!IsVisible()) + return false; + + // Can any of our children handle this? + foreach (var child in Children) + if (child.HandleKeyPressOuter(e)) + return true; + + // Do any widgety behavior (enter text etc) + var handled = HandleKeyPressInner(e); + + // Apply any special logic added by delegates; they return true if they caught the input + if (OnKeyPress(e)) return true; + + return handled; + } + + public static bool HandleKeyPress(KeyInput e) + { + if (SelectedWidget != null) + return SelectedWidget.HandleKeyPressOuter(e); + + if (RootWidget.HandleKeyPressOuter(e)) + return true; + return false; + } + + public abstract void DrawInner(); + + public virtual void Draw() + { + if (IsVisible()) + { + DrawInner(); + foreach (var child in Children) + child.Draw(); + } + } + + public virtual void Tick() + { + if (IsVisible()) + foreach (var child in Children) + child.Tick(); + } + + public virtual void AddChild(Widget child) + { + child.Parent = this; + Children.Add(child); + } + public virtual void RemoveChild(Widget child) { Children.Remove(child); } + public virtual void RemoveChildren() { Children.Clear(); } + + public Widget GetWidget(string id) + { + if (this.Id == id) + return this; + + foreach (var child in Children) + { + var w = child.GetWidget(id); + if (w != null) + return w; + } + return null; + } + + public T GetWidget(string id) where T : Widget + { + var widget = GetWidget(id); + return (widget != null) ? (T)widget : null; + } + + public static void CloseWindow() + { + RootWidget.Children.Remove(WindowList.Pop()); + if (WindowList.Count > 0) + rootWidget.Children.Add(WindowList.Peek()); + } + + public static Widget OpenWindow(string id) + { + return OpenWindow(id, new Dictionary()); + } + + public static Widget OpenWindow(string id, Dictionary args) + { + var window = Game.modData.WidgetLoader.LoadWidget(args, rootWidget, id); + if (WindowList.Count > 0) + rootWidget.Children.Remove(WindowList.Peek()); + WindowList.Push(window); + return window; + } + + public static void DoTick() + { + RootWidget.Tick(); + } + + public static void DoDraw() + { + RootWidget.Draw(); + } + } + + public class ContainerWidget : Widget + { + public Func GetBackground; + public string Background = null; + + public ContainerWidget() + : base() + { + GetBackground = () => Background; + } + + public ContainerWidget(ContainerWidget other) + : base(other) + { + Background = other.Background; + GetBackground = other.GetBackground; + } + + public override void DrawInner() + { + var bg = GetBackground(); + if (bg != null) + WidgetUtils.DrawPanel(bg, RenderBounds); + } + + public override string GetCursor(int2 pos) { return null; } + public override Widget Clone() { return new ContainerWidget(this); } + } + + public interface IWidgetDelegate { } + public interface IWidgetDelegateEx : IWidgetDelegate + { + void Init(); + } } \ No newline at end of file diff --git a/OpenRA.Mods.RA/Widgets/Delegates/ConnectionDialogsDelegate.cs b/OpenRA.Mods.RA/Widgets/Delegates/ConnectionDialogsDelegate.cs index a7702cc2a2..bce395508a 100644 --- a/OpenRA.Mods.RA/Widgets/Delegates/ConnectionDialogsDelegate.cs +++ b/OpenRA.Mods.RA/Widgets/Delegates/ConnectionDialogsDelegate.cs @@ -29,8 +29,8 @@ namespace OpenRA.Mods.RA.Widgets.Delegates widget.GetWidget("CONNECTING_DESC").GetText = () => "Connecting to {0}:{1}...".F(host, port); - } - } + } + } public class ConnectionFailedDelegate : IWidgetDelegate { diff --git a/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs b/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs index 689d5105b1..20a4338e1b 100755 --- a/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs +++ b/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs @@ -23,7 +23,7 @@ using System.Drawing; namespace OpenRA.Mods.RA.Widgets.Delegates { - public class GameInitDelegate : IWidgetDelegate + public class GameInitDelegate : IWidgetDelegateEx { GameInitInfoWidget Info; @@ -31,42 +31,45 @@ namespace OpenRA.Mods.RA.Widgets.Delegates public GameInitDelegate([ObjectCreator.Param] Widget widget) { Info = (widget as GameInitInfoWidget); - - Game.ConnectionStateChanged += orderManager => - { - Widget.CloseWindow(); - switch( orderManager.Connection.ConnectionState ) - { - case ConnectionState.PreConnecting: - Widget.OpenWindow("MAINMENU_BG"); - break; - case ConnectionState.Connecting: - Widget.OpenWindow( "CONNECTING_BG", - new Dictionary { { "host", orderManager.Host }, { "port", orderManager.Port } } ); - break; - case ConnectionState.NotConnected: - Widget.OpenWindow( "CONNECTION_FAILED_BG", - new Dictionary { { "orderManager", orderManager } } ); - break; - case ConnectionState.Connected: - var lobby = Game.OpenWindow(orderManager.world, "SERVER_LOBBY"); - lobby.GetWidget("CHAT_DISPLAY").ClearChat(); - lobby.GetWidget("CHANGEMAP_BUTTON").Visible = true; - lobby.GetWidget("LOCKTEAMS_CHECKBOX").Visible = true; - lobby.GetWidget("ALLOWCHEATS_CHECKBOX").Visible = true; - lobby.GetWidget("DISCONNECT_BUTTON").Visible = true; - break; - } - }; - - if (FileSystem.Exists(Info.TestFile)) - ContinueLoading(widget); - else - { - MainMenuButtonsDelegate.DisplayModSelector(); - ShowInstallMethodDialog(); - } - } + } + + public void Init() + { + Game.ConnectionStateChanged += orderManager => + { + Widget.CloseWindow(); + switch (orderManager.Connection.ConnectionState) + { + case ConnectionState.PreConnecting: + Widget.OpenWindow("MAINMENU_BG"); + break; + case ConnectionState.Connecting: + Widget.OpenWindow("CONNECTING_BG", + new Dictionary { { "host", orderManager.Host }, { "port", orderManager.Port } }); + break; + case ConnectionState.NotConnected: + Widget.OpenWindow("CONNECTION_FAILED_BG", + new Dictionary { { "orderManager", orderManager } }); + break; + case ConnectionState.Connected: + var lobby = Game.OpenWindow(orderManager.world, "SERVER_LOBBY"); + lobby.GetWidget("CHAT_DISPLAY").ClearChat(); + lobby.GetWidget("CHANGEMAP_BUTTON").Visible = true; + lobby.GetWidget("LOCKTEAMS_CHECKBOX").Visible = true; + lobby.GetWidget("ALLOWCHEATS_CHECKBOX").Visible = true; + lobby.GetWidget("DISCONNECT_BUTTON").Visible = true; + break; + } + }; + + if (FileSystem.Exists(Info.TestFile)) + ContinueLoading(); + else + { + MainMenuButtonsDelegate.DisplayModSelector(); + ShowInstallMethodDialog(); + } + } void ShowInstallMethodDialog() { @@ -113,9 +116,9 @@ namespace OpenRA.Mods.RA.Widgets.Delegates }; Action onComplete = () => - { - if (!error) - Game.RunAfterTick(() => ContinueLoading(Info)); + { + if (!error) + Game.RunAfterTick(ContinueLoading); }; if (Info.InstallMode == "ra") @@ -151,19 +154,19 @@ namespace OpenRA.Mods.RA.Widgets.Delegates var error = false; Action parseOutput = s => { - if (s.Substring(0,5) == "Error") + if (s.StartsWith("Error")) { error = true; ShowDownloadError(window, s); } - if (s.Substring(0,6) == "Status") + if (s.StartsWith("Status")) window.GetWidget("STATUS").GetText = () => s.Substring(7).Trim(); }; Action onComplete = () => { if (!error) - Game.RunAfterTick(() => ContinueLoading(Info)); + Game.RunAfterTick(ContinueLoading); }; Game.RunAfterTick(() => Game.Utilities.ExtractZipAsync(file, FileSystem.SpecialPackageRoot+Info.PackagePath, parseOutput, onComplete)); @@ -185,7 +188,7 @@ namespace OpenRA.Mods.RA.Widgets.Delegates } } - void ContinueLoading(Widget widget) + void ContinueLoading() { Game.LoadShellMap(); Widget.RootWidget.RemoveChildren(); @@ -218,6 +221,6 @@ namespace OpenRA.Mods.RA.Widgets.Delegates wc.CancelAsync(); cancelled = true; } - } - } + } + } }