StephaneLenclud@211: using System; StephaneLenclud@211: using System.Collections.Generic; StephaneLenclud@211: using System.ComponentModel; StephaneLenclud@211: using System.Data; StephaneLenclud@219: using System.Diagnostics; StephaneLenclud@211: using System.Drawing; StephaneLenclud@211: using System.Linq; StephaneLenclud@211: using System.Text; StephaneLenclud@211: using System.Threading.Tasks; StephaneLenclud@211: using System.Windows.Forms; StephaneLenclud@219: using SharpLib.Display; StephaneLenclud@211: using SharpLib.Ear; StephaneLenclud@219: using System.Reflection; StephaneLenclud@211: StephaneLenclud@211: namespace SharpDisplayManager StephaneLenclud@211: { StephaneLenclud@214: /// StephaneLenclud@214: /// Action edit dialog form. StephaneLenclud@214: /// StephaneLenclud@211: public partial class FormEditAction : Form StephaneLenclud@211: { StephaneLenclud@211: public SharpLib.Ear.Action Action = null; StephaneLenclud@211: StephaneLenclud@211: public FormEditAction() StephaneLenclud@211: { StephaneLenclud@211: InitializeComponent(); StephaneLenclud@211: } StephaneLenclud@211: StephaneLenclud@211: private void FormEditAction_Load(object sender, EventArgs e) StephaneLenclud@211: { StephaneLenclud@211: //Populate registered actions Stephane@212: foreach (string key in ManagerEventAction.Current.ActionTypes.Keys) StephaneLenclud@211: { StephaneLenclud@214: ItemActionType item = new ItemActionType(ManagerEventAction.Current.ActionTypes[key]); StephaneLenclud@214: comboBoxActionType.Items.Add(item); StephaneLenclud@211: } StephaneLenclud@211: StephaneLenclud@211: comboBoxActionType.SelectedIndex = 0; StephaneLenclud@211: } StephaneLenclud@211: StephaneLenclud@211: private void buttonOk_Click(object sender, EventArgs e) StephaneLenclud@211: { StephaneLenclud@220: FetchPropertiesValue(Action); StephaneLenclud@211: } StephaneLenclud@211: StephaneLenclud@211: private void FormEditAction_Validating(object sender, CancelEventArgs e) StephaneLenclud@211: { StephaneLenclud@211: StephaneLenclud@211: } StephaneLenclud@219: StephaneLenclud@219: private void comboBoxActionType_SelectedIndexChanged(object sender, EventArgs e) StephaneLenclud@219: { StephaneLenclud@219: //Instantiate an action corresponding to our type StephaneLenclud@219: Action = (SharpLib.Ear.Action)Activator.CreateInstance(((ItemActionType)comboBoxActionType.SelectedItem).Type); StephaneLenclud@219: StephaneLenclud@219: //Create input fields StephaneLenclud@219: UpdateTableLayoutPanel(Action); StephaneLenclud@219: } StephaneLenclud@219: StephaneLenclud@220: StephaneLenclud@220: /// StephaneLenclud@220: /// Get properties values from our generated input fields StephaneLenclud@220: /// StephaneLenclud@220: private void FetchPropertiesValue(SharpLib.Ear.Action aAction) StephaneLenclud@220: { StephaneLenclud@220: int ctrlIndex = 0; StephaneLenclud@220: foreach (PropertyInfo pi in aAction.GetType().GetProperties()) StephaneLenclud@220: { StephaneLenclud@220: AttributeActionProperty[] attributes = StephaneLenclud@220: ((AttributeActionProperty[]) pi.GetCustomAttributes(typeof(AttributeActionProperty), true)); StephaneLenclud@220: if (attributes.Length != 1) StephaneLenclud@220: { StephaneLenclud@220: continue; StephaneLenclud@220: } StephaneLenclud@220: StephaneLenclud@220: AttributeActionProperty attribute = attributes[0]; StephaneLenclud@220: StephaneLenclud@220: if (!IsPropertyTypeSupported(pi)) StephaneLenclud@220: { StephaneLenclud@220: continue; StephaneLenclud@220: } StephaneLenclud@220: StephaneLenclud@220: GetPropertyValueFromControl(iTableLayoutPanel.Controls[ctrlIndex+1], pi, aAction); //+1 otherwise we get the label StephaneLenclud@220: StephaneLenclud@220: ctrlIndex+=2; //Jump over the label too StephaneLenclud@220: } StephaneLenclud@220: } StephaneLenclud@220: StephaneLenclud@220: /// StephaneLenclud@220: /// Extend this function to support reading new types of properties. StephaneLenclud@220: /// StephaneLenclud@220: /// StephaneLenclud@220: private void GetPropertyValueFromControl(Control aControl, PropertyInfo aInfo, SharpLib.Ear.Action aAction) StephaneLenclud@220: { StephaneLenclud@220: if (aInfo.PropertyType == typeof(int)) StephaneLenclud@220: { StephaneLenclud@220: NumericUpDown ctrl=(NumericUpDown)aControl; StephaneLenclud@220: aInfo.SetValue(aAction,(int)ctrl.Value); StephaneLenclud@220: } StephaneLenclud@220: else if (aInfo.PropertyType.IsEnum) StephaneLenclud@220: { StephaneLenclud@220: // Instantiate our enum StephaneLenclud@220: object enumValue= Activator.CreateInstance(aInfo.PropertyType); StephaneLenclud@220: // Parse our enum from combo box StephaneLenclud@221: enumValue = Enum.Parse(aInfo.PropertyType,((ComboBox)aControl).SelectedItem.ToString()); StephaneLenclud@221: //enumValue = ((ComboBox)aControl).SelectedValue; StephaneLenclud@220: // Set enum value StephaneLenclud@220: aInfo.SetValue(aAction, enumValue); StephaneLenclud@220: } StephaneLenclud@222: else if (aInfo.PropertyType == typeof(bool)) StephaneLenclud@222: { StephaneLenclud@222: CheckBox ctrl = (CheckBox)aControl; StephaneLenclud@222: aInfo.SetValue(aAction, ctrl.Checked); StephaneLenclud@222: } StephaneLenclud@225: else if (aInfo.PropertyType == typeof(string)) StephaneLenclud@225: { StephaneLenclud@225: TextBox ctrl = (TextBox)aControl; StephaneLenclud@225: aInfo.SetValue(aAction, ctrl.Text); StephaneLenclud@225: } StephaneLenclud@225: //TODO: add support for other types here StephaneLenclud@220: } StephaneLenclud@220: StephaneLenclud@220: /// StephaneLenclud@220: /// StephaneLenclud@220: /// StephaneLenclud@220: /// StephaneLenclud@220: /// StephaneLenclud@220: private Control CreateControlForProperty(PropertyInfo aInfo, AttributeActionProperty aAttribute, SharpLib.Ear.Action aAction) StephaneLenclud@220: { StephaneLenclud@220: if (aInfo.PropertyType == typeof(int)) StephaneLenclud@220: { StephaneLenclud@220: //Integer properties are using numeric editor StephaneLenclud@222: NumericUpDown ctrl = new NumericUpDown(); StephaneLenclud@222: ctrl.AutoSize = true; StephaneLenclud@220: ctrl.Minimum = Int32.Parse(aAttribute.Minimum); StephaneLenclud@220: ctrl.Maximum = Int32.Parse(aAttribute.Maximum); StephaneLenclud@220: ctrl.Increment = Int32.Parse(aAttribute.Increment); StephaneLenclud@220: ctrl.Value = (int)aInfo.GetValue(aAction); StephaneLenclud@220: return ctrl; StephaneLenclud@220: } StephaneLenclud@220: else if (aInfo.PropertyType.IsEnum) StephaneLenclud@220: { StephaneLenclud@220: //Enum properties are using combo box StephaneLenclud@220: ComboBox ctrl = new ComboBox(); StephaneLenclud@224: ctrl.AutoSize = true; StephaneLenclud@224: ctrl.Sorted = true; StephaneLenclud@220: ctrl.DropDownStyle = ComboBoxStyle.DropDownList; StephaneLenclud@221: //Data source is fine but it gives us duplicate entries for duplicated enum values StephaneLenclud@221: //ctrl.DataSource = Enum.GetValues(aInfo.PropertyType); StephaneLenclud@221: StephaneLenclud@223: //Therefore we need to explicitly create our items StephaneLenclud@224: Size cbSize = new Size(0,0); StephaneLenclud@221: foreach (string name in aInfo.PropertyType.GetEnumNames()) StephaneLenclud@221: { StephaneLenclud@221: ctrl.Items.Add(name.ToString()); StephaneLenclud@224: Graphics g = this.CreateGraphics(); StephaneLenclud@224: //Since combobox autosize would not work we need to get measure text ourselves StephaneLenclud@224: SizeF size=g.MeasureString(name.ToString(), ctrl.Font); StephaneLenclud@224: cbSize.Width = Math.Max(cbSize.Width,(int)size.Width); StephaneLenclud@224: cbSize.Height = Math.Max(cbSize.Height, (int)size.Height); StephaneLenclud@221: } StephaneLenclud@221: StephaneLenclud@224: //Make sure our combobox is large enough StephaneLenclud@224: ctrl.MinimumSize = cbSize; StephaneLenclud@224: StephaneLenclud@222: // Instantiate our enum StephaneLenclud@222: object enumValue = Activator.CreateInstance(aInfo.PropertyType); StephaneLenclud@222: enumValue = aInfo.GetValue(aAction); StephaneLenclud@222: //Set the current item StephaneLenclud@222: ctrl.SelectedItem = enumValue.ToString(); StephaneLenclud@221: StephaneLenclud@220: return ctrl; StephaneLenclud@220: } StephaneLenclud@222: else if (aInfo.PropertyType == typeof(bool)) StephaneLenclud@222: { StephaneLenclud@222: CheckBox ctrl = new CheckBox(); StephaneLenclud@222: ctrl.AutoSize = true; StephaneLenclud@222: ctrl.Text = aAttribute.Description; StephaneLenclud@222: ctrl.Checked = (bool)aInfo.GetValue(aAction); StephaneLenclud@222: return ctrl; StephaneLenclud@222: } StephaneLenclud@225: else if (aInfo.PropertyType == typeof(string)) StephaneLenclud@225: { StephaneLenclud@225: TextBox ctrl = new TextBox(); StephaneLenclud@225: ctrl.AutoSize = true; StephaneLenclud@225: ctrl.Text = (string)aInfo.GetValue(aAction); StephaneLenclud@225: return ctrl; StephaneLenclud@225: } StephaneLenclud@225: //TODO: add support for other control type here StephaneLenclud@220: StephaneLenclud@220: return null; StephaneLenclud@220: } StephaneLenclud@220: StephaneLenclud@220: /// StephaneLenclud@220: /// Don't forget to extend that one and adding types StephaneLenclud@220: /// StephaneLenclud@220: /// StephaneLenclud@220: private bool IsPropertyTypeSupported(PropertyInfo aInfo) StephaneLenclud@220: { StephaneLenclud@220: if (aInfo.PropertyType == typeof(int)) StephaneLenclud@220: { StephaneLenclud@220: return true; StephaneLenclud@220: } StephaneLenclud@220: else if (aInfo.PropertyType.IsEnum) StephaneLenclud@220: { StephaneLenclud@220: return true; StephaneLenclud@220: } StephaneLenclud@222: else if (aInfo.PropertyType == typeof(bool)) StephaneLenclud@222: { StephaneLenclud@222: return true; StephaneLenclud@222: } StephaneLenclud@225: else if (aInfo.PropertyType == typeof(string)) StephaneLenclud@225: { StephaneLenclud@225: return true; StephaneLenclud@225: } StephaneLenclud@225: //TODO: add support for other type here StephaneLenclud@220: StephaneLenclud@220: return false; StephaneLenclud@220: } StephaneLenclud@220: StephaneLenclud@219: /// StephaneLenclud@219: /// Update our table layout. StephaneLenclud@219: /// Will instantiated every field control as defined by our action. StephaneLenclud@219: /// Fields must be specified by rows from the left. StephaneLenclud@219: /// StephaneLenclud@219: /// StephaneLenclud@219: private void UpdateTableLayoutPanel(SharpLib.Ear.Action aAction) StephaneLenclud@219: { StephaneLenclud@219: toolTip.RemoveAll(); StephaneLenclud@219: //Debug.Print("UpdateTableLayoutPanel") StephaneLenclud@219: //First clean our current panel StephaneLenclud@219: iTableLayoutPanel.Controls.Clear(); StephaneLenclud@219: iTableLayoutPanel.RowStyles.Clear(); StephaneLenclud@219: iTableLayoutPanel.ColumnStyles.Clear(); StephaneLenclud@219: iTableLayoutPanel.RowCount = 0; StephaneLenclud@219: StephaneLenclud@219: //We always want two columns: one for label and one for the field StephaneLenclud@219: iTableLayoutPanel.ColumnCount = 2; StephaneLenclud@219: iTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); StephaneLenclud@219: iTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); StephaneLenclud@219: StephaneLenclud@219: StephaneLenclud@219: if (aAction == null) StephaneLenclud@219: { StephaneLenclud@219: //Just drop it StephaneLenclud@219: return; StephaneLenclud@219: } StephaneLenclud@219: StephaneLenclud@219: //IEnumerable properties = aAction.GetType().GetProperties().Where( StephaneLenclud@219: // prop => Attribute.IsDefined(prop, typeof(AttributeActionProperty))); StephaneLenclud@219: StephaneLenclud@219: StephaneLenclud@219: foreach (PropertyInfo pi in aAction.GetType().GetProperties()) StephaneLenclud@219: { StephaneLenclud@219: AttributeActionProperty[] attributes = ((AttributeActionProperty[])pi.GetCustomAttributes(typeof(AttributeActionProperty), true)); StephaneLenclud@219: if (attributes.Length != 1) StephaneLenclud@219: { StephaneLenclud@219: continue; StephaneLenclud@219: } StephaneLenclud@219: StephaneLenclud@219: AttributeActionProperty attribute = attributes[0]; StephaneLenclud@220: StephaneLenclud@220: //Before anything we need to check if that kind of property is supported by our UI StephaneLenclud@220: //Create the editor StephaneLenclud@220: Control ctrl = CreateControlForProperty(pi, attribute, aAction); StephaneLenclud@220: if (ctrl == null) StephaneLenclud@220: { StephaneLenclud@220: //Property type not supported StephaneLenclud@220: continue; StephaneLenclud@220: } StephaneLenclud@220: StephaneLenclud@219: //Add a new row StephaneLenclud@219: iTableLayoutPanel.RowCount++; StephaneLenclud@219: iTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize)); StephaneLenclud@219: //Create the label StephaneLenclud@219: Label label = new Label(); StephaneLenclud@224: label.AutoSize = true; StephaneLenclud@224: label.Dock = DockStyle.Fill; StephaneLenclud@224: label.TextAlign = ContentAlignment.MiddleCenter; StephaneLenclud@219: label.Text = attribute.Name; StephaneLenclud@219: toolTip.SetToolTip(label, attribute.Description); StephaneLenclud@219: iTableLayoutPanel.Controls.Add(label, 0, iTableLayoutPanel.RowCount-1); StephaneLenclud@219: StephaneLenclud@220: //Add our editor to our form StephaneLenclud@220: iTableLayoutPanel.Controls.Add(ctrl, 1, iTableLayoutPanel.RowCount - 1); StephaneLenclud@223: //Add tooltip to editor too StephaneLenclud@223: toolTip.SetToolTip(ctrl, attribute.Description); StephaneLenclud@219: StephaneLenclud@220: } StephaneLenclud@219: StephaneLenclud@219: } StephaneLenclud@219: StephaneLenclud@211: } StephaneLenclud@211: }