Adding support for enumerated action property edition.
authorStephaneLenclud
Tue, 26 Jul 2016 15:05:57 +0200
changeset 220e5910d7b6a81
parent 219 99c407831232
child 221 5770478e1fe3
Adding support for enumerated action property edition.
Server/Actions/ActionCecDevice.cs
Server/Actions/ActionCecDevicePowerOn.cs
Server/Actions/ActionCecDeviceStandby.cs
Server/FormEditAction.Designer.cs
Server/FormEditAction.cs
Server/MainForm.cs
Server/SharpDisplayManager.csproj
SharpLibEar/Action.cs
SharpLibEar/ActionSleep.cs
SharpLibEar/AttributeActionProperty.cs
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/Server/Actions/ActionCecDevice.cs	Tue Jul 26 15:05:57 2016 +0200
     1.3 @@ -0,0 +1,26 @@
     1.4 +using CecSharp;
     1.5 +using SharpLib.Ear;
     1.6 +using System;
     1.7 +using System.Collections.Generic;
     1.8 +using System.Linq;
     1.9 +using System.Runtime.InteropServices;
    1.10 +using System.Runtime.Serialization;
    1.11 +using System.Text;
    1.12 +using System.Threading.Tasks;
    1.13 +
    1.14 +namespace SharpDisplayManager
    1.15 +{
    1.16 +    [DataContract]
    1.17 +    public abstract class ActionCecDevice: SharpLib.Ear.Action
    1.18 +    {
    1.19 +        [DataMember]
    1.20 +        [AttributeActionProperty
    1.21 +            (
    1.22 +            Id = "CEC.Device",
    1.23 +            Name = "Device",
    1.24 +            Description = "The logical address used by this action."
    1.25 +            )
    1.26 +        ]
    1.27 +        public CecLogicalAddress Device { get; set; }
    1.28 +    }
    1.29 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Server/Actions/ActionCecDevicePowerOn.cs	Tue Jul 26 15:05:57 2016 +0200
     2.3 @@ -0,0 +1,40 @@
     2.4 +using CecSharp;
     2.5 +using SharpLib.Ear;
     2.6 +using System;
     2.7 +using System.Collections.Generic;
     2.8 +using System.Linq;
     2.9 +using System.Runtime.InteropServices;
    2.10 +using System.Runtime.Serialization;
    2.11 +using System.Text;
    2.12 +using System.Threading.Tasks;
    2.13 +
    2.14 +namespace SharpDisplayManager
    2.15 +{
    2.16 +    [DataContract]
    2.17 +    [AttributeAction(Id = "Cec.Device.PowerOn", Name = "CEC Device Power On", Description = "Turns on the specified CEC device on your HDMI bus.")]
    2.18 +    public class ActionCecDevicePowerOn : ActionCecDevice
    2.19 +    {
    2.20 +        /// <summary>
    2.21 +        /// 
    2.22 +        /// </summary>
    2.23 +        /// <returns></returns>
    2.24 +        public override string Brief()
    2.25 +        {
    2.26 +            return "CEC Power On " + Device.ToString();
    2.27 +        }
    2.28 +
    2.29 +        /// <summary>
    2.30 +        /// 
    2.31 +        /// </summary>
    2.32 +        public override void Execute()
    2.33 +        {
    2.34 +            if (Cec.Client.Static == null)
    2.35 +            {
    2.36 +                Console.WriteLine("WARNING: No CEC client installed.");
    2.37 +                return;
    2.38 +            }
    2.39 +
    2.40 +            Cec.Client.Static.Lib.PowerOnDevices(Device);
    2.41 +        }
    2.42 +    }
    2.43 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/Server/Actions/ActionCecDeviceStandby.cs	Tue Jul 26 15:05:57 2016 +0200
     3.3 @@ -0,0 +1,41 @@
     3.4 +using CecSharp;
     3.5 +using SharpLib.Ear;
     3.6 +using System;
     3.7 +using System.Collections.Generic;
     3.8 +using System.Linq;
     3.9 +using System.Runtime.InteropServices;
    3.10 +using System.Runtime.Serialization;
    3.11 +using System.Text;
    3.12 +using System.Threading.Tasks;
    3.13 +
    3.14 +namespace SharpDisplayManager
    3.15 +{
    3.16 +    [DataContract]
    3.17 +    [AttributeAction(Id = "Cec.Device.Standby", Name = "CEC Device Standby", Description = "Puts on standby the specified CEC device on your HDMI bus.")]
    3.18 +    public class ActionCecDeviceStandby : ActionCecDevice
    3.19 +    {
    3.20 +        /// <summary>
    3.21 +        /// 
    3.22 +        /// </summary>
    3.23 +        /// <returns></returns>
    3.24 +        public override string Brief()
    3.25 +        {
    3.26 +            return "CEC Standby " + Device.ToString();
    3.27 +        }
    3.28 +
    3.29 +        /// <summary>
    3.30 +        /// 
    3.31 +        /// </summary>
    3.32 +        public override void Execute()
    3.33 +        {
    3.34 +            if (Cec.Client.Static == null)
    3.35 +            {
    3.36 +                Console.WriteLine("WARNING: No CEC client installed.");
    3.37 +                return;
    3.38 +            }
    3.39 +
    3.40 +            Cec.Client.Static.Lib.StandbyDevices(Device);
    3.41 +        }
    3.42 +
    3.43 +    }
    3.44 +}
     4.1 --- a/Server/FormEditAction.Designer.cs	Tue Jul 26 11:51:50 2016 +0200
     4.2 +++ b/Server/FormEditAction.Designer.cs	Tue Jul 26 15:05:57 2016 +0200
     4.3 @@ -60,7 +60,7 @@
     4.4              // 
     4.5              this.buttonOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
     4.6              this.buttonOk.DialogResult = System.Windows.Forms.DialogResult.OK;
     4.7 -            this.buttonOk.Location = new System.Drawing.Point(12, 347);
     4.8 +            this.buttonOk.Location = new System.Drawing.Point(12, 72);
     4.9              this.buttonOk.Name = "buttonOk";
    4.10              this.buttonOk.Size = new System.Drawing.Size(75, 23);
    4.11              this.buttonOk.TabIndex = 21;
    4.12 @@ -72,7 +72,7 @@
    4.13              // 
    4.14              this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
    4.15              this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
    4.16 -            this.buttonCancel.Location = new System.Drawing.Point(93, 347);
    4.17 +            this.buttonCancel.Location = new System.Drawing.Point(93, 72);
    4.18              this.buttonCancel.Name = "buttonCancel";
    4.19              this.buttonCancel.Size = new System.Drawing.Size(75, 23);
    4.20              this.buttonCancel.TabIndex = 22;
    4.21 @@ -81,6 +81,10 @@
    4.22              // 
    4.23              // iTableLayoutPanel
    4.24              // 
    4.25 +            this.iTableLayoutPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
    4.26 +            | System.Windows.Forms.AnchorStyles.Left) 
    4.27 +            | System.Windows.Forms.AnchorStyles.Right)));
    4.28 +            this.iTableLayoutPanel.AutoSize = true;
    4.29              this.iTableLayoutPanel.ColumnCount = 2;
    4.30              this.iTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
    4.31              this.iTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
    4.32 @@ -89,7 +93,7 @@
    4.33              this.iTableLayoutPanel.RowCount = 2;
    4.34              this.iTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
    4.35              this.iTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
    4.36 -            this.iTableLayoutPanel.Size = new System.Drawing.Size(373, 114);
    4.37 +            this.iTableLayoutPanel.Size = new System.Drawing.Size(373, 16);
    4.38              this.iTableLayoutPanel.TabIndex = 23;
    4.39              // 
    4.40              // FormEditAction
    4.41 @@ -97,8 +101,9 @@
    4.42              this.AcceptButton = this.buttonOk;
    4.43              this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    4.44              this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    4.45 +            this.AutoSize = true;
    4.46              this.CancelButton = this.buttonCancel;
    4.47 -            this.ClientSize = new System.Drawing.Size(400, 382);
    4.48 +            this.ClientSize = new System.Drawing.Size(400, 107);
    4.49              this.Controls.Add(this.iTableLayoutPanel);
    4.50              this.Controls.Add(this.buttonCancel);
    4.51              this.Controls.Add(this.buttonOk);
     5.1 --- a/Server/FormEditAction.cs	Tue Jul 26 11:51:50 2016 +0200
     5.2 +++ b/Server/FormEditAction.cs	Tue Jul 26 15:05:57 2016 +0200
     5.3 @@ -40,7 +40,7 @@
     5.4  
     5.5          private void buttonOk_Click(object sender, EventArgs e)
     5.6          {
     5.7 -            
     5.8 +            FetchPropertiesValue(Action);
     5.9          }
    5.10  
    5.11          private void FormEditAction_Validating(object sender, CancelEventArgs e)
    5.12 @@ -57,6 +57,105 @@
    5.13              UpdateTableLayoutPanel(Action);
    5.14          }
    5.15  
    5.16 +
    5.17 +        /// <summary>
    5.18 +        /// Get properties values from our generated input fields
    5.19 +        /// </summary>
    5.20 +        private void FetchPropertiesValue(SharpLib.Ear.Action aAction)
    5.21 +        {
    5.22 +            int ctrlIndex = 0;
    5.23 +            foreach (PropertyInfo pi in aAction.GetType().GetProperties())
    5.24 +            {
    5.25 +                AttributeActionProperty[] attributes =
    5.26 +                    ((AttributeActionProperty[]) pi.GetCustomAttributes(typeof(AttributeActionProperty), true));
    5.27 +                if (attributes.Length != 1)
    5.28 +                {
    5.29 +                    continue;
    5.30 +                }
    5.31 +
    5.32 +                AttributeActionProperty attribute = attributes[0];
    5.33 +
    5.34 +                if (!IsPropertyTypeSupported(pi))
    5.35 +                {
    5.36 +                    continue;
    5.37 +                }
    5.38 +
    5.39 +                GetPropertyValueFromControl(iTableLayoutPanel.Controls[ctrlIndex+1], pi, aAction); //+1 otherwise we get the label
    5.40 +
    5.41 +                ctrlIndex+=2; //Jump over the label too
    5.42 +            }
    5.43 +        }
    5.44 +
    5.45 +        /// <summary>
    5.46 +        /// Extend this function to support reading new types of properties.
    5.47 +        /// </summary>
    5.48 +        /// <param name="aAction"></param>
    5.49 +        private void GetPropertyValueFromControl(Control aControl, PropertyInfo aInfo, SharpLib.Ear.Action aAction)
    5.50 +        {
    5.51 +            if (aInfo.PropertyType == typeof(int))
    5.52 +            {
    5.53 +                NumericUpDown ctrl=(NumericUpDown)aControl;
    5.54 +                aInfo.SetValue(aAction,(int)ctrl.Value);
    5.55 +            }
    5.56 +            else if (aInfo.PropertyType.IsEnum)
    5.57 +            {
    5.58 +                // Instantiate our enum
    5.59 +                object enumValue= Activator.CreateInstance(aInfo.PropertyType);
    5.60 +                // Parse our enum from combo box
    5.61 +                //enumValue = Enum.Parse(aInfo.PropertyType,((ComboBox)aControl).SelectedValue.ToString());
    5.62 +                enumValue = ((ComboBox)aControl).SelectedValue;
    5.63 +                // Set enum value
    5.64 +                aInfo.SetValue(aAction, enumValue);
    5.65 +            }
    5.66 +        }
    5.67 +
    5.68 +        /// <summary>
    5.69 +        /// 
    5.70 +        /// </summary>
    5.71 +        /// <param name="aInfo"></param>
    5.72 +        /// <param name="action"></param>
    5.73 +        private Control CreateControlForProperty(PropertyInfo aInfo, AttributeActionProperty aAttribute, SharpLib.Ear.Action aAction)
    5.74 +        {
    5.75 +            if (aInfo.PropertyType == typeof(int))
    5.76 +            {
    5.77 +                //Integer properties are using numeric editor
    5.78 +                NumericUpDown ctrl = new NumericUpDown();                
    5.79 +                ctrl.Minimum = Int32.Parse(aAttribute.Minimum);
    5.80 +                ctrl.Maximum = Int32.Parse(aAttribute.Maximum);
    5.81 +                ctrl.Increment = Int32.Parse(aAttribute.Increment);
    5.82 +                ctrl.Value = (int)aInfo.GetValue(aAction);
    5.83 +                return ctrl;
    5.84 +            }
    5.85 +            else if (aInfo.PropertyType.IsEnum)
    5.86 +            {
    5.87 +                //Enum properties are using combo box
    5.88 +                ComboBox ctrl = new ComboBox();
    5.89 +                ctrl.DropDownStyle = ComboBoxStyle.DropDownList;
    5.90 +                ctrl.DataSource = Enum.GetValues(aInfo.PropertyType);
    5.91 +                return ctrl;
    5.92 +            }
    5.93 +
    5.94 +            return null;
    5.95 +        }
    5.96 +
    5.97 +        /// <summary>
    5.98 +        /// Don't forget to extend that one and adding types
    5.99 +        /// </summary>
   5.100 +        /// <returns></returns>
   5.101 +        private bool IsPropertyTypeSupported(PropertyInfo aInfo)
   5.102 +        {
   5.103 +            if (aInfo.PropertyType == typeof(int))
   5.104 +            {
   5.105 +                return true;
   5.106 +            }
   5.107 +            else if (aInfo.PropertyType.IsEnum)
   5.108 +            {
   5.109 +                return true;
   5.110 +            }
   5.111 +
   5.112 +            return false;
   5.113 +        }
   5.114 +
   5.115          /// <summary>
   5.116          /// Update our table layout.
   5.117          /// Will instantiated every field control as defined by our action.
   5.118 @@ -98,6 +197,16 @@
   5.119                  }
   5.120  
   5.121                  AttributeActionProperty attribute = attributes[0];
   5.122 +
   5.123 +                //Before anything we need to check if that kind of property is supported by our UI
   5.124 +                //Create the editor
   5.125 +                Control ctrl = CreateControlForProperty(pi, attribute, aAction);
   5.126 +                if (ctrl == null)
   5.127 +                {
   5.128 +                    //Property type not supported
   5.129 +                    continue;
   5.130 +                }
   5.131 +
   5.132                  //Add a new row
   5.133                  iTableLayoutPanel.RowCount++;
   5.134                  iTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
   5.135 @@ -107,67 +216,11 @@
   5.136                  toolTip.SetToolTip(label, attribute.Description);
   5.137                  iTableLayoutPanel.Controls.Add(label, 0, iTableLayoutPanel.RowCount-1);
   5.138  
   5.139 +                //Add our editor to our form
   5.140 +                iTableLayoutPanel.Controls.Add(ctrl, 1, iTableLayoutPanel.RowCount - 1);
   5.141  
   5.142 -                //Create the editor
   5.143  
   5.144 -            }
   5.145 -
   5.146 -
   5.147 -            /*
   5.148 -            //Then recreate our rows...
   5.149 -            while (iTableLayoutPanel.RowCount < layout.Rows.Count)
   5.150 -            {
   5.151 -                iTableLayoutPanel.RowCount++;
   5.152 -            }
   5.153 -
   5.154 -            // ...and columns 
   5.155 -            while (iTableLayoutPanel.ColumnCount < layout.Columns.Count)
   5.156 -            {
   5.157 -                iTableLayoutPanel.ColumnCount++;
   5.158 -            }
   5.159 -
   5.160 -            //For each column
   5.161 -            for (int i = 0; i < iTableLayoutPanel.ColumnCount; i++)
   5.162 -            {
   5.163 -                //Create our column styles
   5.164 -                this.iTableLayoutPanel.ColumnStyles.Add(layout.Columns[i]);
   5.165 -
   5.166 -                //For each rows
   5.167 -                for (int j = 0; j < iTableLayoutPanel.RowCount; j++)
   5.168 -                {
   5.169 -                    if (i == 0)
   5.170 -                    {
   5.171 -                        //Create our row styles
   5.172 -                        this.iTableLayoutPanel.RowStyles.Add(layout.Rows[j]);
   5.173 -                    }
   5.174 -                    else
   5.175 -                    {
   5.176 -                        continue;
   5.177 -                    }
   5.178 -                }
   5.179 -            }
   5.180 -
   5.181 -            //For each field
   5.182 -            foreach (DataField field in aClient.Fields)
   5.183 -            {
   5.184 -                if (!field.IsTableField)
   5.185 -                {
   5.186 -                    //That field is not taking part in our table layout skip it
   5.187 -                    continue;
   5.188 -                }
   5.189 -
   5.190 -                TableField tableField = (TableField)field;
   5.191 -
   5.192 -                //Create a control corresponding to the field specified for that cell
   5.193 -                Control control = CreateControlForDataField(tableField);
   5.194 -
   5.195 -                //Add newly created control to our table layout at the specified row and column
   5.196 -                iTableLayoutPanel.Controls.Add(control, tableField.Column, tableField.Row);
   5.197 -                //Make sure we specify column and row span for that new control
   5.198 -                iTableLayoutPanel.SetColumnSpan(control, tableField.ColumnSpan);
   5.199 -                iTableLayoutPanel.SetRowSpan(control, tableField.RowSpan);
   5.200 -            }
   5.201 -            */
   5.202 +            }        
   5.203  
   5.204          }
   5.205  
     6.1 --- a/Server/MainForm.cs	Tue Jul 26 11:51:50 2016 +0200
     6.2 +++ b/Server/MainForm.cs	Tue Jul 26 15:05:57 2016 +0200
     6.3 @@ -324,7 +324,7 @@
     6.4                  // Add our actions for that event
     6.5                  foreach (SharpLib.Ear.Action a in e.Actions)
     6.6                  {
     6.7 -                    TreeNode actionNode = actionsNodes.Nodes.Add(a.Name);
     6.8 +                    TreeNode actionNode = actionsNodes.Nodes.Add(a.Brief());
     6.9                      actionNode.Tag = a;
    6.10                  }
    6.11              }
     7.1 --- a/Server/SharpDisplayManager.csproj	Tue Jul 26 11:51:50 2016 +0200
     7.2 +++ b/Server/SharpDisplayManager.csproj	Tue Jul 26 15:05:57 2016 +0200
     7.3 @@ -154,12 +154,15 @@
     7.4    </ItemGroup>
     7.5    <ItemGroup>
     7.6      <Compile Include="Actions\ActionCecClose.cs" />
     7.7 +    <Compile Include="Actions\ActionCecDevice.cs" />
     7.8      <Compile Include="Actions\ActionCecInactiveSource.cs" />
     7.9      <Compile Include="Actions\ActionCecOpen.cs" />
    7.10 +    <Compile Include="Actions\ActionCecDevicePowerOn.cs" />
    7.11      <Compile Include="Actions\ActionCecPowerOnTv.cs" />
    7.12      <Compile Include="Actions\ActionCecActiveSource.cs" />
    7.13      <Compile Include="Actions\ActionCecScan.cs" />
    7.14      <Compile Include="Actions\ActionCecSendKeypressTvPowerOff.cs" />
    7.15 +    <Compile Include="Actions\ActionCecDeviceStandby.cs" />
    7.16      <Compile Include="Actions\ActionCecStandbyTv.cs" />
    7.17      <Compile Include="Actions\ActionCecSendKeypressTvPowerOn.cs" />
    7.18      <Compile Include="CbtHook.cs" />
     8.1 --- a/SharpLibEar/Action.cs	Tue Jul 26 11:51:50 2016 +0200
     8.2 +++ b/SharpLibEar/Action.cs	Tue Jul 26 15:05:57 2016 +0200
     8.3 @@ -20,6 +20,11 @@
     8.4              private set { }
     8.5          }
     8.6  
     8.7 +        public virtual string Brief()
     8.8 +        {
     8.9 +            return Name;
    8.10 +        }
    8.11 +
    8.12          public int CompareTo(object obj)
    8.13          {
    8.14              //Sort by action name
     9.1 --- a/SharpLibEar/ActionSleep.cs	Tue Jul 26 11:51:50 2016 +0200
     9.2 +++ b/SharpLibEar/ActionSleep.cs	Tue Jul 26 15:05:57 2016 +0200
     9.3 @@ -14,8 +14,16 @@
     9.4      public class ActionSleep : Action
     9.5      {
     9.6          [DataMember]
     9.7 -        [AttributeActionProperty(Id = "Thread.Sleep.Timeout", Name = "Timeout",
     9.8 -            Description = "Specifies the number of milliseconds this action will sleep for.")]
     9.9 +        [AttributeActionProperty
    9.10 +            (
    9.11 +                Id = "Thread.Sleep.Timeout",
    9.12 +                Name = "Timeout (ms)",
    9.13 +                Description = "Specifies the number of milliseconds this action will sleep for.",
    9.14 +                Minimum = "0",
    9.15 +                Maximum = "10000",
    9.16 +                Increment =  "1"
    9.17 +            )
    9.18 +        ]
    9.19          public int TimeoutInMilliseconds { get; set; }
    9.20  
    9.21          public ActionSleep()
    9.22 @@ -29,6 +37,12 @@
    9.23              TimeoutInMilliseconds = aMillisecondsTimeout;
    9.24          }
    9.25  
    9.26 +        public override string Brief()
    9.27 +        {
    9.28 +            return Name + " for " + TimeoutInMilliseconds + " ms";
    9.29 +        }
    9.30 +
    9.31 +
    9.32          public override void Execute()
    9.33          {
    9.34              Thread.Sleep(TimeoutInMilliseconds);
    10.1 --- a/SharpLibEar/AttributeActionProperty.cs	Tue Jul 26 11:51:50 2016 +0200
    10.2 +++ b/SharpLibEar/AttributeActionProperty.cs	Tue Jul 26 15:05:57 2016 +0200
    10.3 @@ -15,5 +15,13 @@
    10.4          public string Id;
    10.5          public string Name;
    10.6          public string Description;
    10.7 +        // For numerics
    10.8 +        public string Minimum;
    10.9 +        public string Maximum;
   10.10 +        public string Increment;
   10.11      }
   10.12 +
   10.13 +
   10.14 +
   10.15 +
   10.16  }