StephaneLenclud@231: using System; StephaneLenclud@231: using System.Collections.Generic; StephaneLenclud@231: using System.ComponentModel; StephaneLenclud@231: using System.Data; StephaneLenclud@231: using System.Diagnostics; StephaneLenclud@231: using System.Drawing; StephaneLenclud@231: using System.Linq; StephaneLenclud@231: using System.Text; StephaneLenclud@231: using System.Threading.Tasks; StephaneLenclud@231: using System.Windows.Forms; StephaneLenclud@231: using SharpLib.Display; StephaneLenclud@231: using SharpLib.Ear; StephaneLenclud@231: using System.Reflection; StephaneLenclud@231: using Microsoft.VisualBasic.CompilerServices; StephaneLenclud@231: using SharpLib.Utils; StephaneLenclud@238: using CodeProject.Dialog; StephaneLenclud@239: using System.IO; StephaneLenclud@231: StephaneLenclud@231: namespace SharpDisplayManager StephaneLenclud@231: { StephaneLenclud@231: /// StephaneLenclud@231: /// Object edit dialog form. StephaneLenclud@231: /// StephaneLenclud@239: public partial class FormEditObject : Form where T: SharpLib.Ear.Object StephaneLenclud@231: { StephaneLenclud@231: public T Object = null; StephaneLenclud@231: StephaneLenclud@231: public FormEditObject() StephaneLenclud@231: { StephaneLenclud@231: InitializeComponent(); StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: /// StephaneLenclud@231: /// StephaneLenclud@231: /// StephaneLenclud@231: /// StephaneLenclud@231: /// StephaneLenclud@231: private void FormEditAction_Load(object sender, EventArgs e) StephaneLenclud@231: { StephaneLenclud@236: // Populate registered object types StephaneLenclud@231: IEnumerable < Type > types = Reflection.GetConcreteClassesDerivedFrom(); StephaneLenclud@231: foreach (Type type in types) StephaneLenclud@231: { StephaneLenclud@231: ItemObjectType item = new ItemObjectType(type); StephaneLenclud@247: iComboBoxObjectType.Items.Add(item); StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: if (Object == null) StephaneLenclud@231: { StephaneLenclud@231: // Creating new issue, select our first item StephaneLenclud@247: iComboBoxObjectType.SelectedIndex = 0; StephaneLenclud@231: } StephaneLenclud@231: else StephaneLenclud@231: { StephaneLenclud@231: // Editing existing object StephaneLenclud@246: // Look up our item in our object type combobox StephaneLenclud@247: foreach (ItemObjectType item in iComboBoxObjectType.Items) StephaneLenclud@231: { StephaneLenclud@231: if (item.Type == Object.GetType()) StephaneLenclud@231: { StephaneLenclud@247: iComboBoxObjectType.SelectedItem = item; StephaneLenclud@231: } StephaneLenclud@231: } StephaneLenclud@246: StephaneLenclud@239: } StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@231: private void buttonOk_Click(object sender, EventArgs e) StephaneLenclud@231: { StephaneLenclud@231: FetchPropertiesValue(Object); StephaneLenclud@239: if (!Object.IsValid()) StephaneLenclud@239: { StephaneLenclud@247: // Tell closing event to cancel StephaneLenclud@239: DialogResult = DialogResult.None; StephaneLenclud@239: } StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@239: StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@239: private void FormEditObject_FormClosing(object sender, FormClosingEventArgs e) StephaneLenclud@231: { StephaneLenclud@247: //Check if we need to cancel the closing of our form. StephaneLenclud@239: e.Cancel = DialogResult == DialogResult.None; StephaneLenclud@246: StephaneLenclud@246: if (!e.Cancel) StephaneLenclud@246: { StephaneLenclud@246: //Exit edit mode StephaneLenclud@246: Object.CurrentState = SharpLib.Ear.Object.State.Rest; StephaneLenclud@246: Object.PropertyChanged -= PropertyChangedEventHandlerThreadSafe; StephaneLenclud@246: } StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@231: private void comboBoxActionType_SelectedIndexChanged(object sender, EventArgs e) StephaneLenclud@231: { StephaneLenclud@231: //Instantiate an action corresponding to our type StephaneLenclud@260: Type objectType = ((ItemObjectType) iComboBoxObjectType.SelectedItem).Type; StephaneLenclud@231: //Create another type of action only if needed StephaneLenclud@260: if (Object == null || Object.GetType() != objectType) StephaneLenclud@231: { StephaneLenclud@266: string name = ""; StephaneLenclud@260: if (Object != null) StephaneLenclud@260: { StephaneLenclud@260: // Make sure we exit edit mode and unhook from events StephaneLenclud@260: Object.CurrentState = SharpLib.Ear.Object.State.Rest; StephaneLenclud@260: Object.PropertyChanged -= PropertyChangedEventHandlerThreadSafe; StephaneLenclud@266: name = Object.Name; StephaneLenclud@260: Object = null; StephaneLenclud@260: } StephaneLenclud@260: Object = (T)Activator.CreateInstance(objectType); StephaneLenclud@266: //Keep the name when changing the type StephaneLenclud@266: Object.Name = name; StephaneLenclud@231: } StephaneLenclud@239: StephaneLenclud@231: //Create input fields StephaneLenclud@247: UpdateControls(); StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: StephaneLenclud@231: /// StephaneLenclud@231: /// Get properties values from our generated input fields StephaneLenclud@231: /// StephaneLenclud@236: private void FetchPropertiesValue(T aObject) StephaneLenclud@231: { StephaneLenclud@231: int ctrlIndex = 0; Stephane@243: //For each of our properties StephaneLenclud@236: foreach (PropertyInfo pi in aObject.GetType().GetProperties()) StephaneLenclud@231: { Stephane@243: //Get our property attribute Stephane@243: AttributeObjectProperty[] attributes = ((AttributeObjectProperty[]) pi.GetCustomAttributes(typeof(AttributeObjectProperty), true)); StephaneLenclud@231: if (attributes.Length != 1) StephaneLenclud@231: { Stephane@243: //No attribute, skip this property then. StephaneLenclud@231: continue; StephaneLenclud@231: } StephaneLenclud@231: AttributeObjectProperty attribute = attributes[0]; StephaneLenclud@231: Stephane@243: //Check that we support this type of property StephaneLenclud@231: if (!IsPropertyTypeSupported(pi)) StephaneLenclud@231: { StephaneLenclud@231: continue; StephaneLenclud@231: } StephaneLenclud@231: Stephane@243: //Now fetch our property value StephaneLenclud@236: GetPropertyValueFromControl(iTableLayoutPanel.Controls[ctrlIndex+1], pi, aObject); //+1 otherwise we get the label StephaneLenclud@231: StephaneLenclud@231: ctrlIndex+=2; //Jump over the label too StephaneLenclud@231: } StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: /// StephaneLenclud@231: /// Extend this function to support reading new types of properties. StephaneLenclud@231: /// StephaneLenclud@236: /// StephaneLenclud@236: private void GetPropertyValueFromControl(Control aControl, PropertyInfo aInfo, T aObject) StephaneLenclud@231: { StephaneLenclud@231: if (aInfo.PropertyType == typeof(int)) StephaneLenclud@231: { StephaneLenclud@231: NumericUpDown ctrl=(NumericUpDown)aControl; StephaneLenclud@236: aInfo.SetValue(aObject,(int)ctrl.Value); StephaneLenclud@231: } StephaneLenclud@231: else if (aInfo.PropertyType.IsEnum) StephaneLenclud@231: { StephaneLenclud@231: // Instantiate our enum StephaneLenclud@231: object enumValue= Activator.CreateInstance(aInfo.PropertyType); StephaneLenclud@231: // Parse our enum from combo box StephaneLenclud@231: enumValue = Enum.Parse(aInfo.PropertyType,((ComboBox)aControl).SelectedItem.ToString()); StephaneLenclud@231: //enumValue = ((ComboBox)aControl).SelectedValue; StephaneLenclud@231: // Set enum value StephaneLenclud@236: aInfo.SetValue(aObject, enumValue); StephaneLenclud@231: } StephaneLenclud@231: else if (aInfo.PropertyType == typeof(bool)) StephaneLenclud@231: { StephaneLenclud@231: CheckBox ctrl = (CheckBox)aControl; StephaneLenclud@236: aInfo.SetValue(aObject, ctrl.Checked); StephaneLenclud@231: } StephaneLenclud@231: else if (aInfo.PropertyType == typeof(string)) StephaneLenclud@231: { StephaneLenclud@231: TextBox ctrl = (TextBox)aControl; StephaneLenclud@236: aInfo.SetValue(aObject, ctrl.Text); StephaneLenclud@231: } StephaneLenclud@238: else if (aInfo.PropertyType == typeof(PropertyFile)) StephaneLenclud@238: { StephaneLenclud@238: Button ctrl = (Button)aControl; StephaneLenclud@238: PropertyFile value = new PropertyFile {FullPath=ctrl.Text}; StephaneLenclud@238: aInfo.SetValue(aObject, value); StephaneLenclud@238: } Stephane@243: else if (aInfo.PropertyType == typeof(PropertyComboBox)) Stephane@243: { Stephane@243: ComboBox ctrl = (ComboBox)aControl; Stephane@243: string currentItem = ctrl.SelectedItem.ToString(); StephaneLenclud@244: PropertyComboBox value = (PropertyComboBox)aInfo.GetValue(aObject); StephaneLenclud@244: value.CurrentItem = currentItem; StephaneLenclud@244: //Not strictly needed but makes sure the set method is called StephaneLenclud@244: aInfo.SetValue(aObject, value); Stephane@243: } StephaneLenclud@250: else if (aInfo.PropertyType == typeof(PropertyButton)) StephaneLenclud@250: { StephaneLenclud@250: Button ctrl = (Button)aControl; StephaneLenclud@250: PropertyButton value = new PropertyButton { Text = ctrl.Text }; StephaneLenclud@250: aInfo.SetValue(aObject, value); StephaneLenclud@250: } Stephane@243: StephaneLenclud@231: //TODO: add support for other types here StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@236: StephaneLenclud@231: /// StephaneLenclud@236: /// Create a control for the given property. StephaneLenclud@231: /// StephaneLenclud@231: /// StephaneLenclud@236: /// StephaneLenclud@236: /// StephaneLenclud@236: /// StephaneLenclud@236: private Control CreateControlForProperty(PropertyInfo aInfo, AttributeObjectProperty aAttribute, T aObject) StephaneLenclud@231: { StephaneLenclud@231: if (aInfo.PropertyType == typeof(int)) StephaneLenclud@231: { StephaneLenclud@231: //Integer properties are using numeric editor StephaneLenclud@231: NumericUpDown ctrl = new NumericUpDown(); StephaneLenclud@231: ctrl.AutoSize = true; StephaneLenclud@231: ctrl.Minimum = Int32.Parse(aAttribute.Minimum); StephaneLenclud@231: ctrl.Maximum = Int32.Parse(aAttribute.Maximum); StephaneLenclud@231: ctrl.Increment = Int32.Parse(aAttribute.Increment); StephaneLenclud@236: ctrl.Value = (int)aInfo.GetValue(aObject); StephaneLenclud@247: // Hook-in change notification after setting the value StephaneLenclud@247: ctrl.ValueChanged += ControlValueChanged; StephaneLenclud@231: return ctrl; StephaneLenclud@231: } StephaneLenclud@231: else if (aInfo.PropertyType.IsEnum) StephaneLenclud@231: { StephaneLenclud@231: //Enum properties are using combo box StephaneLenclud@231: ComboBox ctrl = new ComboBox(); Stephane@243: ctrl.AutoSize = true; Stephane@243: ctrl.Sorted = true; StephaneLenclud@231: ctrl.DropDownStyle = ComboBoxStyle.DropDownList; StephaneLenclud@231: //Data source is fine but it gives us duplicate entries for duplicated enum values StephaneLenclud@231: //ctrl.DataSource = Enum.GetValues(aInfo.PropertyType); StephaneLenclud@231: StephaneLenclud@231: //Therefore we need to explicitly create our items Stephane@243: Size cbSize = new Size(0, 0); StephaneLenclud@231: foreach (string name in aInfo.PropertyType.GetEnumNames()) StephaneLenclud@231: { StephaneLenclud@231: ctrl.Items.Add(name.ToString()); StephaneLenclud@231: Graphics g = this.CreateGraphics(); StephaneLenclud@231: //Since combobox autosize would not work we need to get measure text ourselves Stephane@243: SizeF size = g.MeasureString(name.ToString(), ctrl.Font); Stephane@243: cbSize.Width = Math.Max(cbSize.Width, (int)size.Width); StephaneLenclud@231: cbSize.Height = Math.Max(cbSize.Height, (int)size.Height); StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: //Make sure our combobox is large enough StephaneLenclud@231: ctrl.MinimumSize = cbSize; StephaneLenclud@231: StephaneLenclud@231: // Instantiate our enum StephaneLenclud@231: object enumValue = Activator.CreateInstance(aInfo.PropertyType); StephaneLenclud@236: enumValue = aInfo.GetValue(aObject); StephaneLenclud@231: //Set the current item StephaneLenclud@231: ctrl.SelectedItem = enumValue.ToString(); StephaneLenclud@247: // Hook-in change notification after setting the value StephaneLenclud@247: ctrl.SelectedIndexChanged += ControlValueChanged; StephaneLenclud@231: StephaneLenclud@231: return ctrl; StephaneLenclud@231: } StephaneLenclud@231: else if (aInfo.PropertyType == typeof(bool)) StephaneLenclud@231: { StephaneLenclud@231: CheckBox ctrl = new CheckBox(); StephaneLenclud@231: ctrl.AutoSize = true; StephaneLenclud@231: ctrl.Text = aAttribute.Description; Stephane@243: ctrl.Checked = (bool)aInfo.GetValue(aObject); StephaneLenclud@247: // Hook-in change notification after setting the value StephaneLenclud@247: ctrl.CheckedChanged += ControlValueChanged; StephaneLenclud@231: return ctrl; StephaneLenclud@231: } StephaneLenclud@231: else if (aInfo.PropertyType == typeof(string)) StephaneLenclud@231: { StephaneLenclud@231: TextBox ctrl = new TextBox(); StephaneLenclud@231: ctrl.AutoSize = true; StephaneLenclud@236: ctrl.Text = (string)aInfo.GetValue(aObject); StephaneLenclud@247: // Hook-in change notification after setting the value StephaneLenclud@247: ctrl.TextChanged += ControlValueChanged; StephaneLenclud@231: return ctrl; StephaneLenclud@231: } StephaneLenclud@238: else if (aInfo.PropertyType == typeof(PropertyFile)) StephaneLenclud@238: { StephaneLenclud@238: // We have a file property StephaneLenclud@238: // Create a button that will trigger the open file dialog to select our file. StephaneLenclud@238: Button ctrl = new Button(); StephaneLenclud@238: ctrl.AutoSize = true; StephaneLenclud@238: ctrl.Text = ((PropertyFile)aInfo.GetValue(aObject)).FullPath; StephaneLenclud@238: // Add lambda expression to Click event StephaneLenclud@238: ctrl.Click += (sender, e) => StephaneLenclud@238: { StephaneLenclud@238: // Create open file dialog StephaneLenclud@238: OpenFileDialog ofd = new OpenFileDialog(); StephaneLenclud@238: ofd.RestoreDirectory = true; StephaneLenclud@238: // Use file filter specified by our property StephaneLenclud@238: ofd.Filter = aAttribute.Filter; StephaneLenclud@238: // Show our dialog StephaneLenclud@238: if (DlgBox.ShowDialog(ofd) == DialogResult.OK) StephaneLenclud@238: { StephaneLenclud@238: // Fetch selected file name StephaneLenclud@238: ctrl.Text = ofd.FileName; StephaneLenclud@238: } StephaneLenclud@238: }; StephaneLenclud@238: StephaneLenclud@247: // Hook-in change notification after setting the value StephaneLenclud@247: ctrl.TextChanged += ControlValueChanged; StephaneLenclud@238: return ctrl; StephaneLenclud@238: } Stephane@243: else if (aInfo.PropertyType == typeof(PropertyComboBox)) Stephane@243: { Stephane@243: //ComboBox property Stephane@243: ComboBox ctrl = new ComboBox(); Stephane@243: ctrl.AutoSize = true; Stephane@243: ctrl.Sorted = true; Stephane@243: ctrl.DropDownStyle = ComboBoxStyle.DropDownList; Stephane@243: //Data source is such a pain to set the current item Stephane@243: //ctrl.DataSource = ((PropertyComboBox)aInfo.GetValue(aObject)).Items; Stephane@243: Stephane@243: PropertyComboBox pcb = ((PropertyComboBox)aInfo.GetValue(aObject)); Stephane@243: foreach (string item in pcb.Items) Stephane@243: { Stephane@243: ctrl.Items.Add(item); Stephane@243: } Stephane@243: Stephane@243: ctrl.SelectedItem = ((PropertyComboBox)aInfo.GetValue(aObject)).CurrentItem; Stephane@243: // Stephane@243: return ctrl; Stephane@243: } StephaneLenclud@250: else if (aInfo.PropertyType == typeof(PropertyButton)) StephaneLenclud@250: { StephaneLenclud@250: // We have a button property StephaneLenclud@250: // Create a button that will trigger the custom action. StephaneLenclud@250: Button ctrl = new Button(); StephaneLenclud@250: ctrl.AutoSize = true; StephaneLenclud@250: ctrl.Text = ((PropertyButton)aInfo.GetValue(aObject)).Text; StephaneLenclud@250: // Hook in click event StephaneLenclud@250: ctrl.Click += ((PropertyButton)aInfo.GetValue(aObject)).ClickEventHandler; StephaneLenclud@250: // Hook-in change notification after setting the value StephaneLenclud@250: ctrl.TextChanged += ControlValueChanged; StephaneLenclud@250: return ctrl; StephaneLenclud@250: } StephaneLenclud@250: StephaneLenclud@231: //TODO: add support for other control type here StephaneLenclud@231: return null; StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: /// StephaneLenclud@231: /// Don't forget to extend that one and adding types StephaneLenclud@231: /// StephaneLenclud@231: /// StephaneLenclud@231: private bool IsPropertyTypeSupported(PropertyInfo aInfo) StephaneLenclud@231: { StephaneLenclud@231: if (aInfo.PropertyType == typeof(int)) StephaneLenclud@231: { StephaneLenclud@231: return true; StephaneLenclud@231: } StephaneLenclud@231: else if (aInfo.PropertyType.IsEnum) StephaneLenclud@231: { StephaneLenclud@231: return true; StephaneLenclud@231: } StephaneLenclud@231: else if (aInfo.PropertyType == typeof(bool)) StephaneLenclud@231: { StephaneLenclud@231: return true; StephaneLenclud@231: } StephaneLenclud@231: else if (aInfo.PropertyType == typeof(string)) StephaneLenclud@231: { StephaneLenclud@231: return true; StephaneLenclud@231: } StephaneLenclud@238: else if (aInfo.PropertyType == typeof(PropertyFile)) StephaneLenclud@238: { StephaneLenclud@238: return true; StephaneLenclud@238: } Stephane@243: else if (aInfo.PropertyType == typeof(PropertyComboBox)) Stephane@243: { Stephane@243: return true; Stephane@243: } StephaneLenclud@250: else if (aInfo.PropertyType == typeof(PropertyButton)) StephaneLenclud@250: { StephaneLenclud@250: return true; StephaneLenclud@250: } Stephane@243: StephaneLenclud@231: //TODO: add support for other type here StephaneLenclud@231: StephaneLenclud@231: return false; StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: /// StephaneLenclud@231: /// Update our table layout. StephaneLenclud@246: /// Will instantiated every field control as defined by our object. StephaneLenclud@231: /// StephaneLenclud@231: /// StephaneLenclud@247: private void UpdateControls() StephaneLenclud@231: { StephaneLenclud@247: StephaneLenclud@231: toolTip.RemoveAll(); StephaneLenclud@231: //Debug.Print("UpdateTableLayoutPanel") StephaneLenclud@231: //First clean our current panel StephaneLenclud@231: iTableLayoutPanel.Controls.Clear(); StephaneLenclud@231: iTableLayoutPanel.RowStyles.Clear(); StephaneLenclud@231: iTableLayoutPanel.ColumnStyles.Clear(); StephaneLenclud@231: iTableLayoutPanel.RowCount = 0; StephaneLenclud@231: StephaneLenclud@231: //We always want two columns: one for label and one for the field StephaneLenclud@231: iTableLayoutPanel.ColumnCount = 2; StephaneLenclud@231: iTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); StephaneLenclud@231: iTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); StephaneLenclud@231: StephaneLenclud@231: StephaneLenclud@247: if (Object == null) StephaneLenclud@231: { StephaneLenclud@231: //Just drop it StephaneLenclud@231: return; StephaneLenclud@231: } StephaneLenclud@246: StephaneLenclud@247: UpdateStaticControls(); StephaneLenclud@247: StephaneLenclud@236: //IEnumerable properties = aObject.GetType().GetProperties().Where( StephaneLenclud@231: // prop => Attribute.IsDefined(prop, typeof(AttributeObjectProperty))); StephaneLenclud@231: StephaneLenclud@246: //TODO: Do this whenever a field changes StephaneLenclud@247: iLabelBrief.Text = Object.Brief(); StephaneLenclud@246: StephaneLenclud@231: StephaneLenclud@247: foreach (PropertyInfo pi in Object.GetType().GetProperties()) StephaneLenclud@231: { StephaneLenclud@231: AttributeObjectProperty[] attributes = ((AttributeObjectProperty[])pi.GetCustomAttributes(typeof(AttributeObjectProperty), true)); StephaneLenclud@231: if (attributes.Length != 1) StephaneLenclud@231: { StephaneLenclud@231: continue; StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: AttributeObjectProperty attribute = attributes[0]; StephaneLenclud@231: StephaneLenclud@231: //Before anything we need to check if that kind of property is supported by our UI StephaneLenclud@231: //Create the editor StephaneLenclud@247: Control ctrl = CreateControlForProperty(pi, attribute, Object); StephaneLenclud@231: if (ctrl == null) StephaneLenclud@231: { StephaneLenclud@231: //Property type not supported StephaneLenclud@231: continue; StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: //Add a new row StephaneLenclud@231: iTableLayoutPanel.RowCount++; StephaneLenclud@231: iTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize)); StephaneLenclud@231: //Create the label StephaneLenclud@231: Label label = new Label(); StephaneLenclud@231: label.AutoSize = true; StephaneLenclud@231: label.Dock = DockStyle.Fill; StephaneLenclud@231: label.TextAlign = ContentAlignment.MiddleCenter; StephaneLenclud@231: label.Text = attribute.Name; StephaneLenclud@231: toolTip.SetToolTip(label, attribute.Description); StephaneLenclud@231: iTableLayoutPanel.Controls.Add(label, 0, iTableLayoutPanel.RowCount-1); StephaneLenclud@231: StephaneLenclud@231: //Add our editor to our form StephaneLenclud@231: iTableLayoutPanel.Controls.Add(ctrl, 1, iTableLayoutPanel.RowCount - 1); StephaneLenclud@231: //Add tooltip to editor too StephaneLenclud@231: toolTip.SetToolTip(ctrl, attribute.Description); StephaneLenclud@231: StephaneLenclud@246: } StephaneLenclud@231: StephaneLenclud@246: //Entrer object edit mode StephaneLenclud@246: Object.CurrentState = SharpLib.Ear.Object.State.Edit; StephaneLenclud@246: Object.PropertyChanged += PropertyChangedEventHandlerThreadSafe; StephaneLenclud@246: } StephaneLenclud@246: StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@246: void PropertyChangedEventHandlerThreadSafe(object sender, PropertyChangedEventArgs e) StephaneLenclud@246: { StephaneLenclud@246: if (this.InvokeRequired) StephaneLenclud@246: { StephaneLenclud@246: //Not in the proper thread, invoke ourselves StephaneLenclud@246: PropertyChangedEventHandler d = new PropertyChangedEventHandler(PropertyChangedEventHandlerThreadSafe); StephaneLenclud@246: this.Invoke(d, new object[] { sender, e }); StephaneLenclud@246: } StephaneLenclud@246: else StephaneLenclud@246: { StephaneLenclud@247: // We could test the name of the property that has changed as follow StephaneLenclud@247: // It's currently not needed though StephaneLenclud@247: //if (e.PropertyName == "Brief") StephaneLenclud@246: StephaneLenclud@247: // Our object has changed behind our back. StephaneLenclud@247: // That's currently only the case for HID events that are listening for inputs. StephaneLenclud@250: if (Object is EventHid) StephaneLenclud@250: { StephaneLenclud@250: //HID can't do full control updates for some reason StephaneLenclud@250: //We are getting spammed with HID events after a few clicks StephaneLenclud@250: //We need to investigate, HID bug? StephaneLenclud@250: UpdateStaticControls(); StephaneLenclud@250: } StephaneLenclud@250: else StephaneLenclud@250: { StephaneLenclud@250: UpdateControls(); StephaneLenclud@250: } StephaneLenclud@246: } StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: private void buttonTest_Click(object sender, EventArgs e) StephaneLenclud@231: { StephaneLenclud@231: FetchPropertiesValue(Object); StephaneLenclud@231: StephaneLenclud@231: //If our object has a test method with no parameters just run it then StephaneLenclud@231: MethodInfo info = Object.GetType().GetMethod("Test"); StephaneLenclud@231: if ( info != null && info.GetParameters().Length==0) StephaneLenclud@231: { StephaneLenclud@231: info.Invoke(Object,null); StephaneLenclud@231: } StephaneLenclud@231: StephaneLenclud@231: } StephaneLenclud@247: StephaneLenclud@247: StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: private void ControlValueChanged(object sender, EventArgs e) StephaneLenclud@247: { StephaneLenclud@247: UpdateObject(); StephaneLenclud@247: } StephaneLenclud@247: StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: private void UpdateObject() StephaneLenclud@247: { StephaneLenclud@247: // Update our object with the content of our controls StephaneLenclud@247: FetchPropertiesValue(Object); StephaneLenclud@247: StephaneLenclud@247: UpdateStaticControls(); StephaneLenclud@247: // StephaneLenclud@247: //PerformLayout(); StephaneLenclud@247: } StephaneLenclud@247: StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: private void UpdateStaticControls() StephaneLenclud@247: { StephaneLenclud@247: // Update OK and test button status StephaneLenclud@247: iButtonOk.Enabled = Object.IsValid(); StephaneLenclud@247: iButtonTest.Enabled = iButtonOk.Enabled; StephaneLenclud@247: StephaneLenclud@247: // Update brief title StephaneLenclud@247: iLabelBrief.Text = Object.Brief(); StephaneLenclud@247: StephaneLenclud@247: // Update object description StephaneLenclud@260: iLabelDescription.Text = Object.AttributeDescription; StephaneLenclud@247: } StephaneLenclud@247: StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: /// StephaneLenclud@247: private void iComboBoxObjectType_KeyPress(object sender, KeyPressEventArgs e) StephaneLenclud@247: { StephaneLenclud@247: //Special case for HID events StephaneLenclud@247: if (Object is EventHid) StephaneLenclud@247: { StephaneLenclud@247: //Disable handling of key input as we are using key input for changing our event StephaneLenclud@247: e.Handled = true; StephaneLenclud@247: } StephaneLenclud@247: } StephaneLenclud@260: StephaneLenclud@260: private void iComboBoxObjectType_Enter(object sender, EventArgs e) StephaneLenclud@260: { StephaneLenclud@260: //Only edit HID event when our type combo box has the focus StephaneLenclud@260: // TODO: That's an ugly workaround, fix that somehow. Maybe by only doing HID scan when a button property has the focus StephaneLenclud@260: if (Object is EventHid) StephaneLenclud@260: { StephaneLenclud@260: Object.CurrentState = SharpLib.Ear.Object.State.Edit; StephaneLenclud@260: } StephaneLenclud@260: } StephaneLenclud@260: StephaneLenclud@260: private void iComboBoxObjectType_Leave(object sender, EventArgs e) StephaneLenclud@260: { StephaneLenclud@260: //Only edit HID event when our type combo box has the focus StephaneLenclud@260: // TODO: That's an ugly workaround, fix that somehow. Maybe by only doing HID scan when a button property has the focus StephaneLenclud@260: if (Object is EventHid) StephaneLenclud@260: { StephaneLenclud@260: Object.CurrentState = SharpLib.Ear.Object.State.Rest; StephaneLenclud@260: } StephaneLenclud@260: } StephaneLenclud@231: } StephaneLenclud@231: }