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: }