Adding support for enumerated action property edition.
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 }