[longomatch] Add support for action links in buttons



commit 552429fbdf3cf903a0bc1ec4d4025787d333e88c
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Thu Apr 9 22:14:03 2015 +0200

    Add support for action links in buttons

 LongoMatch.Core/Common/Enums.cs              |   13 +++
 LongoMatch.Core/Common/Exceptions.cs         |    4 +
 LongoMatch.Core/LongoMatch.Core.csproj       |    1 +
 LongoMatch.Core/Makefile.am                  |    1 +
 LongoMatch.Core/Store/ActionLink.cs          |  148 ++++++++++++++++++++++++++
 LongoMatch.Core/Store/DashboardButton.cs     |   10 ++
 LongoMatch.Core/Store/Templates/Dashboard.cs |  111 +++++++++++++++++---
 Tests/Core/Store/Templates/TestDashboard.cs  |   36 +++++--
 Tests/Core/Store/TestActionLink.cs           |   82 ++++++++++++++
 Tests/Makefile.am                            |    2 +
 Tests/Tests.csproj                           |    2 +
 11 files changed, 385 insertions(+), 25 deletions(-)
---
diff --git a/LongoMatch.Core/Common/Enums.cs b/LongoMatch.Core/Common/Enums.cs
index 4287e9c..94434a1 100644
--- a/LongoMatch.Core/Common/Enums.cs
+++ b/LongoMatch.Core/Common/Enums.cs
@@ -427,4 +427,17 @@ namespace LongoMatch.Core.Common
                LiveAnalysisReview,
                Analysis,
        }
+
+       public enum LinkAction
+       {
+               Toggle,
+               Replicate,
+       }
+
+       public enum TeamLinkAction
+       {
+               Clear,
+               Keep,
+               Invert
+       }
 }
diff --git a/LongoMatch.Core/Common/Exceptions.cs b/LongoMatch.Core/Common/Exceptions.cs
index 884d7e9..478e2f0 100644
--- a/LongoMatch.Core/Common/Exceptions.cs
+++ b/LongoMatch.Core/Common/Exceptions.cs
@@ -99,5 +99,9 @@ namespace LongoMatch.Core.Common
                {
                }
        }
+
+       public class CircularDependencyException: Exception
+       {
+       }
 }
 
diff --git a/LongoMatch.Core/LongoMatch.Core.csproj b/LongoMatch.Core/LongoMatch.Core.csproj
index df3479f..1f202b5 100644
--- a/LongoMatch.Core/LongoMatch.Core.csproj
+++ b/LongoMatch.Core/LongoMatch.Core.csproj
@@ -144,6 +144,7 @@
       <Link>AssemblyInfo.cs</Link>
     </Compile>
     <Compile Include="Interfaces\GUI\IViewPort.cs" />
+    <Compile Include="Store\ActionLink.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Common\" />
diff --git a/LongoMatch.Core/Makefile.am b/LongoMatch.Core/Makefile.am
index 01dd3b5..ff81a26 100644
--- a/LongoMatch.Core/Makefile.am
+++ b/LongoMatch.Core/Makefile.am
@@ -76,6 +76,7 @@ SOURCES = ../AssemblyInfo/AssemblyInfo.cs \
        Stats/SubCategoryStat.cs \
        Stats/TeamStats.cs \
        Stats/TimerStats.cs \
+       Store/ActionLink.cs \
        Store/Coordinates.cs \
        Store/DashboardButton.cs \
        Store/Drawables/Angle.cs \
diff --git a/LongoMatch.Core/Store/ActionLink.cs b/LongoMatch.Core/Store/ActionLink.cs
new file mode 100644
index 0000000..0abdd96
--- /dev/null
+++ b/LongoMatch.Core/Store/ActionLink.cs
@@ -0,0 +1,148 @@
+//
+//  Copyright (C) 2015 Fluendo S.A.
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using LongoMatch.Core.Common;
+using Newtonsoft.Json;
+
+namespace LongoMatch.Core.Store
+{
+       /// <summary>
+       /// Defines an action link between 2 buttons in a <see 
cref="LongoMatch.Core.Store.Templates.Dashboard"/>.
+       /// </summary>
+       [Serializable]
+       public class ActionLink
+       {
+               public ActionLink ()
+               {
+                       KeepCommonTags = true;
+                       KeepPlayerTags = true;
+                       TeamAction = TeamLinkAction.Keep;
+                       SourceTags = new List<Tag> ();
+                       DestionationTags = new List<Tag> ();
+               }
+
+               /// <summary>
+               /// The source button of the link
+               /// </summary>
+               [JsonIgnore]
+               public DashboardButton SourceButton {
+                       get;
+                       set;
+               }
+
+               /// <summary>
+               /// A list of tags that needs to match in the source
+               /// </summary>
+               [JsonIgnore]
+               public List<Tag> SourceTags {
+                       get;
+                       set;
+               }
+
+               /// <summary>
+               /// The destination button of the link
+               /// </summary>
+               public DashboardButton DestinationButton {
+                       get;
+                       set;
+               }
+
+               /// <summary>
+               /// A list of tags that needs to be set in the destination
+               /// </summary>
+               public List<Tag> DestionationTags {
+                       get;
+                       set;
+               }
+
+               /// <summary>
+               /// The type of action that will be performed in the destination.
+               /// </summary>
+               public LinkAction Action {
+                       get;
+                       set;
+               }
+
+               /// <summary>
+               /// The type of action that will be performed in the destination
+               /// for team tagged in the source event.
+               /// </summary>
+               public TeamLinkAction TeamAction {
+                       get;
+                       set;
+               }
+
+               /// <summary>
+               /// If <c>true</c>, players tagged in the source event will be copied
+               /// </summary>
+               public bool KeepPlayerTags {
+                       get;
+                       set;
+               }
+
+               /// <summary>
+               /// If <c>true</c>, common tags will be copied
+               /// </summary>
+               public bool KeepCommonTags {
+                       get;
+                       set;
+               }
+
+               public override bool Equals (object obj)
+               {
+                       ActionLink link = obj as ActionLink;
+                       if (link == null)
+                               return false;
+                       if (link.SourceButton != SourceButton ||
+                           link.DestinationButton != DestinationButton) {
+                               return false;
+                       }
+                       if (!link.SourceTags.SequenceEqual (SourceTags) ||
+                           !link.DestionationTags.SequenceEqual (DestionationTags)) {
+                               return false;
+                       }
+                       return true;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return base.GetHashCode ();
+               }
+
+               public static bool operator == (ActionLink l1, ActionLink l2)
+               {
+                       if (Object.ReferenceEquals (l1, l2)) {
+                               return true;
+                       }
+                       
+                       if ((object)l1 == null || (object)l2 == null) {
+                               return false;
+                       }
+                       
+                       return l1.Equals (l2);
+               }
+
+               public static bool operator != (ActionLink l1, ActionLink l2)
+               {
+                       return !(l1 == l2);
+               }
+       }
+}
+
diff --git a/LongoMatch.Core/Store/DashboardButton.cs b/LongoMatch.Core/Store/DashboardButton.cs
index 4ff72bd..2540b1d 100644
--- a/LongoMatch.Core/Store/DashboardButton.cs
+++ b/LongoMatch.Core/Store/DashboardButton.cs
@@ -18,6 +18,7 @@
 using System;
 using LongoMatch.Core.Common;
 using Newtonsoft.Json;
+using System.Collections.Generic;
 
 namespace LongoMatch.Core.Store
 {
@@ -34,6 +35,7 @@ namespace LongoMatch.Core.Store
                        BackgroundColor = Color.Red;
                        TextColor = Config.Style.PaletteBackgroundLight;
                        HotKey = new HotKey ();
+                       ActionLinks = new List<ActionLink> ();
                }
 
                public virtual string Name {
@@ -76,6 +78,14 @@ namespace LongoMatch.Core.Store
                        set;
                }
 
+               /// <summary>
+               /// A list with all the outgoing links of this button
+               /// </summary>
+               public List<ActionLink> ActionLinks {
+                       get;
+                       set;
+               }
+
                [JsonIgnore]
                public Color LightColor {
                        get {
diff --git a/LongoMatch.Core/Store/Templates/Dashboard.cs b/LongoMatch.Core/Store/Templates/Dashboard.cs
index ed128d1..1c9b10f 100644
--- a/LongoMatch.Core/Store/Templates/Dashboard.cs
+++ b/LongoMatch.Core/Store/Templates/Dashboard.cs
@@ -21,25 +21,19 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Runtime.Serialization;
-using Newtonsoft.Json;
-
-using Mono.Unix;
 using LongoMatch.Core.Common;
 using LongoMatch.Core.Interfaces;
+using Mono.Unix;
+using Newtonsoft.Json;
 
 using Image = LongoMatch.Core.Common.Image;
-using System.Collections.ObjectModel;
 
 namespace LongoMatch.Core.Store.Templates
 {
 
        /// <summary>
-       /// I am a template for the analysis categories used in a project.
-       /// I describe each one of the categories and provide the default values
-       /// to use to create plys in a specific category.
-       /// The position of the category in the index is very important and should
-       /// respect the same index used in the plays list inside a project.
-       /// The <see cref="LongoMatch.DB.Project"/> must handle all the changes
+       /// A dashboard contains a set of <see cref="DashboardButton"/> disposed
+       /// in a grid to code events in a the game's timeline.
        /// </summary>
        [Serializable]
        public class Dashboard: IStorable, ITemplate
@@ -50,9 +44,6 @@ namespace LongoMatch.Core.Store.Templates
                const int MIN_WIDTH = 320;
                const int MIN_HEIGHT = 240;
 
-               /// <summary>
-               /// Creates a new template
-               /// </summary>
                public Dashboard ()
                {
                        try {
@@ -88,58 +79,96 @@ namespace LongoMatch.Core.Store.Templates
                        InitializeLists ();
                }
 
-               
+               /// <summary>
+               /// Unique ID describing the dashboard
+               /// </summary>
                public Guid ID {
                        get;
                        set;
                }
 
+               /// <summary>
+               /// When set to <c>true</c> the dashboard is treated as a system dashboard
+               /// and it can't be modified
+               /// </summary>
                [JsonIgnore]
                public bool Static {
                        get;
                        set;
                }
 
+               /// <summary>
+               /// A list with all the buttons in this dashboard
+               /// </summary>
                public List<DashboardButton> List {
                        get;
                        set;
                }
 
+               /// <summary>
+               /// The name of the dashboard
+               /// </summary>
                public string Name {
                        get;
                        set;
                }
 
+               /// <summary>
+               /// A list with the default periods for this dashboard.
+               /// When a new project is created this list will be used
+               /// to the same amount of periods in this list and with
+               /// the same names
+               /// </summary>
+               /// <value>The game periods.</value>
                public List<string> GamePeriods {
                        get;
                        set;
                }
 
+               /// <summary>
+               /// The icon used for this dashboard
+               /// </summary>
                public Image Image {
                        get;
                        set;
                }
 
+               /// <summary>
+               /// The field background image
+               /// </summary>
                public Image FieldBackground {
                        get;
                        set;
                }
 
+               /// <summary>
+               /// The half field background image
+               /// </summary>
                public Image HalfFieldBackground {
                        get;
                        set;
                }
 
+               /// <summary>
+               /// The goal background image
+               /// </summary>
                public Image GoalBackground {
                        get;
                        set;
                }
 
+               /// <summary>
+               /// When set to <c>true</c>, creating a new event does not show the dialog
+               /// window to edit the event details.
+               /// </summary>
                public bool DisablePopupWindow {
                        get;
                        set;
                }
 
+               /// <summary>
+               /// A list with all the timers used in this dashboard
+               /// </summary>
                [JsonIgnore]
                public List<Timer> Timers {
                        get {
@@ -175,6 +204,12 @@ namespace LongoMatch.Core.Store.Templates
                        }
                }
 
+               /// <summary>
+               /// Changes a hotkey for a button in the dashboard checking
+               /// the hotkey is not already in use.
+               /// </summary>
+               /// <param name="button">Button to change the hotkey.</param>
+               /// <param name="hotkey">New hotkey for the button.</param>
                public void ChangeHotkey (DashboardButton button, HotKey hotkey)
                {
                        if (List.Count (d => d.HotKey == hotkey) > 0) {
@@ -184,6 +219,10 @@ namespace LongoMatch.Core.Store.Templates
                        }
                }
 
+               /// <summary>
+               /// Adds the default tags to a button
+               /// </summary>
+               /// <param name="ev">The event type where the tags will be added</param>
                public void AddDefaultTags (AnalysisEventType ev)
                {
                        ev.Tags.Add (new Tag (Catalog.GetString ("Success"),
@@ -192,6 +231,27 @@ namespace LongoMatch.Core.Store.Templates
                                Catalog.GetString ("Outcome")));
                }
 
+               /// <summary>
+               /// Checks if there are circular depedencies in the buttons links.
+               /// </summary>
+               /// <returns><c>false</c> if no circular dependencies where found.</returns>
+               public bool HasCircularDependencies ()
+               {
+                       foreach (DashboardButton button in List) {
+                               try {
+                                       CheckButtonLinks (button, new List<DashboardButton> ());
+                               } catch (CircularDependencyException) {
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+
+               /// <summary>
+               /// Adds a new <see cref="AnalysisEventButton"/> with the default values
+               /// </summary>
+               /// <returns>A new button.</returns>
+               /// <param name="index">Index of this button used to name it</param>
                public AnalysisEventButton AddDefaultItem (int index)
                {
                        AnalysisEventButton button;
@@ -221,6 +281,11 @@ namespace LongoMatch.Core.Store.Templates
                        return button;
                }
 
+               /// <summary>
+               /// Creates a new dashboard with a default set of buttons
+               /// </summary>
+               /// <returns>the new dashboadrd.</returns>
+               /// <param name="count">Number of <see cref="AnalysisEventButton"/> to add.</param>
                public static Dashboard DefaultTemplate (int count)
                {
                        TagButton tagbutton;
@@ -289,10 +354,26 @@ namespace LongoMatch.Core.Store.Templates
                        return template;
                }
 
-               private void FillDefaultTemplate (int count)
+               void FillDefaultTemplate (int count)
                {
                        for (int i = 1; i <= count; i++)
                                AddDefaultItem (i - 1);
                }
+
+               void CheckButtonLinks (DashboardButton button, List<DashboardButton> traversed = null)
+               {
+                       if (traversed == null)
+                               traversed = new List<DashboardButton> ();
+
+                       if (traversed.Contains (button)) {
+                               throw new CircularDependencyException ();
+                       } else {
+                               traversed.Add (button);
+                       }
+
+                       foreach (ActionLink l in button.ActionLinks) {
+                               CheckButtonLinks (l.DestinationButton, traversed);
+                       }
+               }
        }
 }
diff --git a/Tests/Core/Store/Templates/TestDashboard.cs b/Tests/Core/Store/Templates/TestDashboard.cs
index 91d5c2c..2c3a355 100644
--- a/Tests/Core/Store/Templates/TestDashboard.cs
+++ b/Tests/Core/Store/Templates/TestDashboard.cs
@@ -24,10 +24,10 @@ using LongoMatch.Core.Store.Templates;
 
 namespace Tests.Core
 {
-       [TestFixture()]
+       [TestFixture ()]
        public class TestDashboard
        {
-               [Test()]
+               [Test ()]
                public void TestSerialization ()
                {
                        Dashboard cat = new Dashboard ();
@@ -38,9 +38,9 @@ namespace Tests.Core
                        cat.GamePeriods = new List<string> ();
                        cat.GamePeriods.Add ("1");
                        cat.GamePeriods.Add ("2");
-                       cat.List.Add ( new AnalysisEventButton {Name = "cat1"});
-                       cat.List.Add ( new {Name = "cat2"});
-                       cat.List.Add ( new CategoryButton {Name = "cat3"});
+                       cat.List.Add (new AnalysisEventButton { Name = "cat1" });
+                       cat.List.Add (new AnalysisEventButton { Name = "cat2" });
+                       cat.List.Add (new AnalysisEventButton { Name = "cat3" });
                        
                        Utils.CheckSerialization (cat);
                        
@@ -48,12 +48,28 @@ namespace Tests.Core
                        Assert.AreEqual (cat.ID, newcat.ID);
                        Assert.AreEqual (cat.Name, newcat.Name);
                        Assert.AreEqual (cat.GamePeriods.Count, newcat.GamePeriods.Count);
-                       Assert.AreEqual (cat.GamePeriods[0], newcat.GamePeriods[0]);
-                       Assert.AreEqual (cat.GamePeriods[1], newcat.GamePeriods[1]);
+                       Assert.AreEqual (cat.GamePeriods [0], newcat.GamePeriods [0]);
+                       Assert.AreEqual (cat.GamePeriods [1], newcat.GamePeriods [1]);
                        Assert.AreEqual (cat.List.Count, newcat.List.Count);
-                       Assert.AreEqual (cat.CategoriesList[0].ID, newcat.CategoriesList[0].ID);
-                       Assert.AreEqual (cat.CategoriesList[1].ID, newcat.CategoriesList[1].ID);
-                       Assert.AreEqual (cat.CategoriesList[2].ID, newcat.CategoriesList[2].ID);
+               }
+
+               [Test ()]
+               public void TestCircularDepdencies ()
+               {
+                       Dashboard dashboard = new Dashboard ();
+                       DashboardButton b1 = new DashboardButton ();
+                       DashboardButton b2 = new DashboardButton ();
+                       DashboardButton b3 = new DashboardButton ();
+                       dashboard.List.Add (b1);
+                       dashboard.List.Add (b2);
+                       dashboard.List.Add (b3);
+
+                       b1.ActionLinks.Add (new ActionLink { DestinationButton = b2 });
+                       Assert.IsFalse (dashboard.HasCircularDependencies ());
+                       b2.ActionLinks.Add (new ActionLink { DestinationButton = b3 });
+                       Assert.IsFalse (dashboard.HasCircularDependencies ());
+                       b3.ActionLinks.Add (new ActionLink { DestinationButton = b1 });
+                       Assert.IsTrue (dashboard.HasCircularDependencies ());
                }
        }
 }
diff --git a/Tests/Core/Store/TestActionLink.cs b/Tests/Core/Store/TestActionLink.cs
new file mode 100644
index 0000000..9962226
--- /dev/null
+++ b/Tests/Core/Store/TestActionLink.cs
@@ -0,0 +1,82 @@
+//
+//  Copyright (C) 2015 Fluendo S.A.
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+using System;
+using NUnit.Framework;
+using LongoMatch.Core.Store;
+using LongoMatch.Core.Common;
+using System.Collections.Generic;
+
+namespace Tests.Core.Store
+{
+       [TestFixture ()]
+       public class TestActionLink
+       {
+
+               ActionLink CreateLink ()
+               {
+                       ActionLink link = new ActionLink ();
+                       link.SourceButton = new DashboardButton ();
+                       link.SourceTags = new List<Tag> { new Tag ("tag1") };
+                       link.DestinationButton = new DashboardButton ();
+                       link.DestionationTags = new List<Tag> { new Tag ("tag2") };
+                       link.Action = LinkAction.Toggle;
+                       link.TeamAction = TeamLinkAction.Invert;
+                       link.KeepCommonTags = false;
+                       link.KeepPlayerTags = false;
+                       return link;
+               }
+
+               [Test ()]
+               public void TestSerialization ()
+               {
+                       ActionLink link = new ActionLink ();
+
+                       Utils.CheckSerialization (link);
+
+                       link = CreateLink ();
+
+                       ActionLink link2 = Utils.SerializeDeserialize (link);
+                       Assert.AreNotEqual (link.SourceTags, link2.SourceTags);
+                       Assert.AreEqual (link.DestionationTags, link2.DestionationTags);
+                       Assert.AreEqual (link.Action, link2.Action);
+                       Assert.AreEqual (link.TeamAction, link2.TeamAction);
+                       Assert.AreEqual (link.KeepCommonTags, link2.KeepCommonTags);
+                       Assert.AreEqual (link.KeepPlayerTags, link2.KeepPlayerTags);
+               }
+
+               [Test ()]
+               public void TestEquality ()
+               {
+                       ActionLink link = CreateLink ();
+                       ActionLink link2 = new ActionLink ();
+                       Assert.IsTrue (link != link2);
+                       Assert.AreNotEqual (link, link2);
+                       link2.SourceButton = link.SourceButton;
+                       Assert.AreNotEqual (link, link2);
+                       link2.DestinationButton = link.DestinationButton;
+                       Assert.AreNotEqual (link, link2);
+                       link2.SourceTags = new List<Tag> { new Tag ("tag1") }; 
+                       Assert.AreNotEqual (link, link2);
+                       link2.DestionationTags = new List<Tag> { new Tag ("tag2") }; 
+                       Assert.IsTrue (link == link2);
+                       Assert.IsTrue (link.Equals (link2));
+               }
+
+       }
+}
+
diff --git a/Tests/Makefile.am b/Tests/Makefile.am
index a0d052b..6b5dfca 100644
--- a/Tests/Makefile.am
+++ b/Tests/Makefile.am
@@ -17,7 +17,9 @@ SOURCES = Core/Common/TestColor.cs \
        Core/Store/Drawables/TestRectangle.cs \
        Core/Store/Drawables/TestText.cs \
        Core/Store/Playlists/TestPlaylistPlayElement.cs \
+       Core/Store/Templates/TestDashboard.cs \
        Core/Store/Templates/TestTeamTemplate.cs \
+       Core/Store/TestActionLink.cs \
        Core/Store/TestCoordinates.cs \
        Core/Store/TestDashboardButton.cs \
        Core/Store/TestEventType.cs \
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 4f8ccbe..964f421 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -83,6 +83,8 @@
     <Compile Include="Services\TestRenderingJobsManager.cs" />
     <Compile Include="Core\Store\Playlists\TestPlaylistPlayElement.cs" />
     <Compile Include="Services\TestPlayerController.cs" />
+    <Compile Include="Core\Store\TestActionLink.cs" />
+    <Compile Include="Core\Store\Templates\TestDashboard.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\LongoMatch.Core\LongoMatch.Core.csproj">


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]