Server/FormEditObject.cs
author StephaneLenclud
Wed, 17 Aug 2016 13:41:26 +0200
changeset 236 6ba20e02d04f
parent 231 4c706feaf706
child 238 c92587ddabcd
permissions -rw-r--r--
Updating HarmonyHub to v0.3.0.
Adding untested Harmony command action.
     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Data;
     5 using System.Diagnostics;
     6 using System.Drawing;
     7 using System.Linq;
     8 using System.Text;
     9 using System.Threading.Tasks;
    10 using System.Windows.Forms;
    11 using SharpLib.Display;
    12 using SharpLib.Ear;
    13 using System.Reflection;
    14 using Microsoft.VisualBasic.CompilerServices;
    15 using SharpLib.Utils;
    16 
    17 namespace SharpDisplayManager
    18 {
    19     /// <summary>
    20     /// Object edit dialog form.
    21     /// </summary>
    22     public partial class FormEditObject<T> : Form where T : class
    23     {
    24         public T Object = null;
    25 
    26         public FormEditObject()
    27         {
    28             InitializeComponent();
    29         }
    30 
    31         /// <summary>
    32         /// 
    33         /// </summary>
    34         /// <param name="sender"></param>
    35         /// <param name="e"></param>
    36         private void FormEditAction_Load(object sender, EventArgs e)
    37         {
    38             // Populate registered object types
    39             IEnumerable < Type > types = Reflection.GetConcreteClassesDerivedFrom<T>();
    40             foreach (Type type in types)
    41             {
    42                 ItemObjectType item = new ItemObjectType(type);
    43                 comboBoxActionType.Items.Add(item);
    44             }
    45 
    46             if (Object == null)
    47             {
    48                 // Creating new issue, select our first item
    49                 comboBoxActionType.SelectedIndex = 0;
    50             }
    51             else
    52             {
    53                 // Editing existing object
    54                 // Look up our item in our combobox 
    55                 foreach (ItemObjectType item in comboBoxActionType.Items)
    56                 {
    57                     if (item.Type == Object.GetType())
    58                     {
    59                         comboBoxActionType.SelectedItem = item;
    60                     }
    61                 }
    62             }            
    63         }
    64 
    65         private void buttonOk_Click(object sender, EventArgs e)
    66         {
    67             FetchPropertiesValue(Object);
    68         }
    69 
    70         private void FormEditAction_Validating(object sender, CancelEventArgs e)
    71         {
    72 
    73         }
    74 
    75         private void comboBoxActionType_SelectedIndexChanged(object sender, EventArgs e)
    76         {
    77             //Instantiate an action corresponding to our type
    78             Type actionType = ((ItemObjectType) comboBoxActionType.SelectedItem).Type;
    79             //Create another type of action only if needed
    80             if (Object == null || Object.GetType() != actionType)
    81             {
    82                 Object = (T)Activator.CreateInstance(actionType);
    83             }
    84             
    85             //Create input fields
    86             UpdateTableLayoutPanel(Object);
    87         }
    88 
    89 
    90         /// <summary>
    91         /// Get properties values from our generated input fields
    92         /// </summary>
    93         private void FetchPropertiesValue(T aObject)
    94         {
    95             int ctrlIndex = 0;
    96             foreach (PropertyInfo pi in aObject.GetType().GetProperties())
    97             {
    98                 AttributeObjectProperty[] attributes =
    99                     ((AttributeObjectProperty[]) pi.GetCustomAttributes(typeof(AttributeObjectProperty), true));
   100                 if (attributes.Length != 1)
   101                 {
   102                     continue;
   103                 }
   104 
   105                 AttributeObjectProperty attribute = attributes[0];
   106 
   107                 if (!IsPropertyTypeSupported(pi))
   108                 {
   109                     continue;
   110                 }
   111 
   112                 GetPropertyValueFromControl(iTableLayoutPanel.Controls[ctrlIndex+1], pi, aObject); //+1 otherwise we get the label
   113 
   114                 ctrlIndex+=2; //Jump over the label too
   115             }
   116         }
   117 
   118         /// <summary>
   119         /// Extend this function to support reading new types of properties.
   120         /// </summary>
   121         /// <param name="aObject"></param>
   122         private void GetPropertyValueFromControl(Control aControl, PropertyInfo aInfo, T aObject)
   123         {
   124             if (aInfo.PropertyType == typeof(int))
   125             {
   126                 NumericUpDown ctrl=(NumericUpDown)aControl;
   127                 aInfo.SetValue(aObject,(int)ctrl.Value);
   128             }
   129             else if (aInfo.PropertyType.IsEnum)
   130             {
   131                 // Instantiate our enum
   132                 object enumValue= Activator.CreateInstance(aInfo.PropertyType);
   133                 // Parse our enum from combo box
   134                 enumValue = Enum.Parse(aInfo.PropertyType,((ComboBox)aControl).SelectedItem.ToString());
   135                 //enumValue = ((ComboBox)aControl).SelectedValue;
   136                 // Set enum value
   137                 aInfo.SetValue(aObject, enumValue);
   138             }
   139             else if (aInfo.PropertyType == typeof(bool))
   140             {
   141                 CheckBox ctrl = (CheckBox)aControl;
   142                 aInfo.SetValue(aObject, ctrl.Checked);
   143             }
   144             else if (aInfo.PropertyType == typeof(string))
   145             {
   146                 TextBox ctrl = (TextBox)aControl;
   147                 aInfo.SetValue(aObject, ctrl.Text);
   148             }
   149             //TODO: add support for other types here
   150         }
   151 
   152 
   153         /// <summary>
   154         /// Create a control for the given property.
   155         /// </summary>
   156         /// <param name="aInfo"></param>
   157         /// <param name="aAttribute"></param>
   158         /// <param name="aObject"></param>
   159         /// <returns></returns>
   160         private Control CreateControlForProperty(PropertyInfo aInfo, AttributeObjectProperty aAttribute, T aObject)
   161         {
   162             if (aInfo.PropertyType == typeof(int))
   163             {
   164                 //Integer properties are using numeric editor
   165                 NumericUpDown ctrl = new NumericUpDown();
   166                 ctrl.AutoSize = true;
   167                 ctrl.Minimum = Int32.Parse(aAttribute.Minimum);
   168                 ctrl.Maximum = Int32.Parse(aAttribute.Maximum);
   169                 ctrl.Increment = Int32.Parse(aAttribute.Increment);
   170                 ctrl.Value = (int)aInfo.GetValue(aObject);
   171                 return ctrl;
   172             }
   173             else if (aInfo.PropertyType.IsEnum)
   174             {
   175                 //Enum properties are using combo box
   176                 ComboBox ctrl = new ComboBox();
   177                 ctrl.AutoSize = true;                
   178                 ctrl.Sorted = true;                
   179                 ctrl.DropDownStyle = ComboBoxStyle.DropDownList;
   180                 //Data source is fine but it gives us duplicate entries for duplicated enum values
   181                 //ctrl.DataSource = Enum.GetValues(aInfo.PropertyType);
   182 
   183                 //Therefore we need to explicitly create our items
   184                 Size cbSize = new Size(0,0);
   185                 foreach (string name in aInfo.PropertyType.GetEnumNames())
   186                 {
   187                     ctrl.Items.Add(name.ToString());
   188                     Graphics g = this.CreateGraphics();
   189                     //Since combobox autosize would not work we need to get measure text ourselves
   190                     SizeF size=g.MeasureString(name.ToString(), ctrl.Font);
   191                     cbSize.Width = Math.Max(cbSize.Width,(int)size.Width);
   192                     cbSize.Height = Math.Max(cbSize.Height, (int)size.Height);
   193                 }
   194 
   195                 //Make sure our combobox is large enough
   196                 ctrl.MinimumSize = cbSize;
   197 
   198                 // Instantiate our enum
   199                 object enumValue = Activator.CreateInstance(aInfo.PropertyType);
   200                 enumValue = aInfo.GetValue(aObject);
   201                 //Set the current item
   202                 ctrl.SelectedItem = enumValue.ToString();
   203 
   204                 return ctrl;
   205             }
   206             else if (aInfo.PropertyType == typeof(bool))
   207             {
   208                 CheckBox ctrl = new CheckBox();
   209                 ctrl.AutoSize = true;
   210                 ctrl.Text = aAttribute.Description;
   211                 ctrl.Checked = (bool)aInfo.GetValue(aObject);                
   212                 return ctrl;
   213             }
   214             else if (aInfo.PropertyType == typeof(string))
   215             {
   216                 TextBox ctrl = new TextBox();
   217                 ctrl.AutoSize = true;
   218                 ctrl.Text = (string)aInfo.GetValue(aObject);
   219                 return ctrl;
   220             }
   221             //TODO: add support for other control type here
   222 
   223             return null;
   224         }
   225 
   226         /// <summary>
   227         /// Don't forget to extend that one and adding types
   228         /// </summary>
   229         /// <returns></returns>
   230         private bool IsPropertyTypeSupported(PropertyInfo aInfo)
   231         {
   232             if (aInfo.PropertyType == typeof(int))
   233             {
   234                 return true;
   235             }
   236             else if (aInfo.PropertyType.IsEnum)
   237             {
   238                 return true;
   239             }
   240             else if (aInfo.PropertyType == typeof(bool))
   241             {
   242                 return true;
   243             }
   244             else if (aInfo.PropertyType == typeof(string))
   245             {
   246                 return true;
   247             }
   248             //TODO: add support for other type here
   249 
   250             return false;
   251         }
   252 
   253         /// <summary>
   254         /// Update our table layout.
   255         /// Will instantiated every field control as defined by our action.
   256         /// Fields must be specified by rows from the left.
   257         /// </summary>
   258         /// <param name="aLayout"></param>
   259         private void UpdateTableLayoutPanel(T aObject)
   260         {
   261             toolTip.RemoveAll();
   262             //Debug.Print("UpdateTableLayoutPanel")
   263             //First clean our current panel
   264             iTableLayoutPanel.Controls.Clear();
   265             iTableLayoutPanel.RowStyles.Clear();
   266             iTableLayoutPanel.ColumnStyles.Clear();
   267             iTableLayoutPanel.RowCount = 0;
   268 
   269             //We always want two columns: one for label and one for the field
   270             iTableLayoutPanel.ColumnCount = 2;
   271             iTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
   272             iTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
   273 
   274 
   275             if (aObject == null)
   276             {
   277                 //Just drop it
   278                 return;
   279             }
   280             
   281             //IEnumerable<PropertyInfo> properties = aObject.GetType().GetProperties().Where(
   282             //    prop => Attribute.IsDefined(prop, typeof(AttributeObjectProperty)));
   283 
   284 
   285             foreach (PropertyInfo pi in aObject.GetType().GetProperties())
   286             {
   287                 AttributeObjectProperty[] attributes = ((AttributeObjectProperty[])pi.GetCustomAttributes(typeof(AttributeObjectProperty), true));
   288                 if (attributes.Length != 1)
   289                 {
   290                     continue;
   291                 }
   292 
   293                 AttributeObjectProperty attribute = attributes[0];
   294 
   295                 //Before anything we need to check if that kind of property is supported by our UI
   296                 //Create the editor
   297                 Control ctrl = CreateControlForProperty(pi, attribute, aObject);
   298                 if (ctrl == null)
   299                 {
   300                     //Property type not supported
   301                     continue;
   302                 }
   303 
   304                 //Add a new row
   305                 iTableLayoutPanel.RowCount++;
   306                 iTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
   307                 //Create the label
   308                 Label label = new Label();
   309                 label.AutoSize = true;
   310                 label.Dock = DockStyle.Fill;
   311                 label.TextAlign = ContentAlignment.MiddleCenter;
   312                 label.Text = attribute.Name;
   313                 toolTip.SetToolTip(label, attribute.Description);
   314                 iTableLayoutPanel.Controls.Add(label, 0, iTableLayoutPanel.RowCount-1);
   315 
   316                 //Add our editor to our form
   317                 iTableLayoutPanel.Controls.Add(ctrl, 1, iTableLayoutPanel.RowCount - 1);
   318                 //Add tooltip to editor too
   319                 toolTip.SetToolTip(ctrl, attribute.Description);
   320 
   321             }        
   322 
   323         }
   324 
   325         private void buttonTest_Click(object sender, EventArgs e)
   326         {
   327             FetchPropertiesValue(Object);
   328 
   329             //If our object has a test method with no parameters just run it then
   330             MethodInfo info = Object.GetType().GetMethod("Test");
   331             if ( info != null && info.GetParameters().Length==0)
   332             {
   333                 info.Invoke(Object,null);
   334             }
   335 
   336         }
   337     }
   338 }