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