Server/FormEditObject.cs
author StephaneLenclud
Sun, 15 Jan 2017 18:49:06 +0100
changeset 279 10f0de70b69b
parent 260 d44943088c67
permissions -rw-r--r--
Ground work for display layout support.
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@238
    16
using CodeProject.Dialog;
StephaneLenclud@239
    17
using System.IO;
StephaneLenclud@231
    18
StephaneLenclud@231
    19
namespace SharpDisplayManager
StephaneLenclud@231
    20
{
StephaneLenclud@231
    21
    /// <summary>
StephaneLenclud@231
    22
    /// Object edit dialog form.
StephaneLenclud@231
    23
    /// </summary>
StephaneLenclud@239
    24
    public partial class FormEditObject<T> : Form where T: SharpLib.Ear.Object
StephaneLenclud@231
    25
    {
StephaneLenclud@231
    26
        public T Object = null;
StephaneLenclud@231
    27
StephaneLenclud@231
    28
        public FormEditObject()
StephaneLenclud@231
    29
        {
StephaneLenclud@231
    30
            InitializeComponent();
StephaneLenclud@231
    31
        }
StephaneLenclud@231
    32
StephaneLenclud@231
    33
        /// <summary>
StephaneLenclud@231
    34
        /// 
StephaneLenclud@231
    35
        /// </summary>
StephaneLenclud@231
    36
        /// <param name="sender"></param>
StephaneLenclud@231
    37
        /// <param name="e"></param>
StephaneLenclud@231
    38
        private void FormEditAction_Load(object sender, EventArgs e)
StephaneLenclud@231
    39
        {
StephaneLenclud@236
    40
            // Populate registered object types
StephaneLenclud@231
    41
            IEnumerable < Type > types = Reflection.GetConcreteClassesDerivedFrom<T>();
StephaneLenclud@231
    42
            foreach (Type type in types)
StephaneLenclud@231
    43
            {
StephaneLenclud@231
    44
                ItemObjectType item = new ItemObjectType(type);
StephaneLenclud@247
    45
                iComboBoxObjectType.Items.Add(item);
StephaneLenclud@231
    46
            }
StephaneLenclud@231
    47
StephaneLenclud@231
    48
            if (Object == null)
StephaneLenclud@231
    49
            {
StephaneLenclud@231
    50
                // Creating new issue, select our first item
StephaneLenclud@247
    51
                iComboBoxObjectType.SelectedIndex = 0;
StephaneLenclud@231
    52
            }
StephaneLenclud@231
    53
            else
StephaneLenclud@231
    54
            {
StephaneLenclud@231
    55
                // Editing existing object
StephaneLenclud@246
    56
                // Look up our item in our object type combobox
StephaneLenclud@247
    57
                foreach (ItemObjectType item in iComboBoxObjectType.Items)
StephaneLenclud@231
    58
                {
StephaneLenclud@231
    59
                    if (item.Type == Object.GetType())
StephaneLenclud@231
    60
                    {
StephaneLenclud@247
    61
                        iComboBoxObjectType.SelectedItem = item;
StephaneLenclud@231
    62
                    }
StephaneLenclud@231
    63
                }
StephaneLenclud@246
    64
StephaneLenclud@239
    65
            }
StephaneLenclud@231
    66
        }
StephaneLenclud@231
    67
StephaneLenclud@247
    68
        /// <summary>
StephaneLenclud@247
    69
        /// 
StephaneLenclud@247
    70
        /// </summary>
StephaneLenclud@247
    71
        /// <param name="sender"></param>
StephaneLenclud@247
    72
        /// <param name="e"></param>
StephaneLenclud@231
    73
        private void buttonOk_Click(object sender, EventArgs e)
StephaneLenclud@231
    74
        {
StephaneLenclud@231
    75
            FetchPropertiesValue(Object);
StephaneLenclud@239
    76
            if (!Object.IsValid())
StephaneLenclud@239
    77
            {
StephaneLenclud@247
    78
                // Tell closing event to cancel
StephaneLenclud@239
    79
                DialogResult = DialogResult.None;
StephaneLenclud@239
    80
            }
StephaneLenclud@231
    81
        }
StephaneLenclud@231
    82
StephaneLenclud@239
    83
StephaneLenclud@247
    84
        /// <summary>
StephaneLenclud@247
    85
        /// 
StephaneLenclud@247
    86
        /// </summary>
StephaneLenclud@247
    87
        /// <param name="sender"></param>
StephaneLenclud@247
    88
        /// <param name="e"></param>
StephaneLenclud@239
    89
        private void FormEditObject_FormClosing(object sender, FormClosingEventArgs e)
StephaneLenclud@231
    90
        {
StephaneLenclud@247
    91
            //Check if we need to cancel the closing of our form.
StephaneLenclud@239
    92
            e.Cancel = DialogResult == DialogResult.None;
StephaneLenclud@246
    93
StephaneLenclud@246
    94
            if (!e.Cancel)
StephaneLenclud@246
    95
            {
StephaneLenclud@246
    96
                //Exit edit mode
StephaneLenclud@246
    97
                Object.CurrentState = SharpLib.Ear.Object.State.Rest;
StephaneLenclud@246
    98
                Object.PropertyChanged -= PropertyChangedEventHandlerThreadSafe;
StephaneLenclud@246
    99
            }
StephaneLenclud@231
   100
        }
StephaneLenclud@231
   101
StephaneLenclud@247
   102
        /// <summary>
StephaneLenclud@247
   103
        /// 
StephaneLenclud@247
   104
        /// </summary>
StephaneLenclud@247
   105
        /// <param name="sender"></param>
StephaneLenclud@247
   106
        /// <param name="e"></param>
StephaneLenclud@231
   107
        private void comboBoxActionType_SelectedIndexChanged(object sender, EventArgs e)
StephaneLenclud@231
   108
        {
StephaneLenclud@231
   109
            //Instantiate an action corresponding to our type
StephaneLenclud@260
   110
            Type objectType = ((ItemObjectType) iComboBoxObjectType.SelectedItem).Type;
StephaneLenclud@231
   111
            //Create another type of action only if needed
StephaneLenclud@260
   112
            if (Object == null || Object.GetType() != objectType)
StephaneLenclud@231
   113
            {
StephaneLenclud@266
   114
                string name = "";
StephaneLenclud@260
   115
                if (Object != null)
StephaneLenclud@260
   116
                {
StephaneLenclud@260
   117
                    // Make sure we exit edit mode and unhook from events
StephaneLenclud@260
   118
                    Object.CurrentState = SharpLib.Ear.Object.State.Rest;
StephaneLenclud@260
   119
                    Object.PropertyChanged -= PropertyChangedEventHandlerThreadSafe;
StephaneLenclud@266
   120
                    name = Object.Name;
StephaneLenclud@260
   121
                    Object = null;
StephaneLenclud@260
   122
                }
StephaneLenclud@260
   123
                Object = (T)Activator.CreateInstance(objectType);
StephaneLenclud@266
   124
                //Keep the name when changing the type
StephaneLenclud@266
   125
                Object.Name = name;
StephaneLenclud@231
   126
            }
StephaneLenclud@239
   127
StephaneLenclud@231
   128
            //Create input fields
StephaneLenclud@247
   129
            UpdateControls();
StephaneLenclud@231
   130
        }
StephaneLenclud@231
   131
StephaneLenclud@231
   132
StephaneLenclud@231
   133
        /// <summary>
StephaneLenclud@231
   134
        /// Get properties values from our generated input fields
StephaneLenclud@231
   135
        /// </summary>
StephaneLenclud@236
   136
        private void FetchPropertiesValue(T aObject)
StephaneLenclud@231
   137
        {
StephaneLenclud@231
   138
            int ctrlIndex = 0;
Stephane@243
   139
            //For each of our properties
StephaneLenclud@236
   140
            foreach (PropertyInfo pi in aObject.GetType().GetProperties())
StephaneLenclud@231
   141
            {
Stephane@243
   142
                //Get our property attribute
Stephane@243
   143
                AttributeObjectProperty[] attributes = ((AttributeObjectProperty[]) pi.GetCustomAttributes(typeof(AttributeObjectProperty), true));
StephaneLenclud@231
   144
                if (attributes.Length != 1)
StephaneLenclud@231
   145
                {
Stephane@243
   146
                    //No attribute, skip this property then.
StephaneLenclud@231
   147
                    continue;
StephaneLenclud@231
   148
                }
StephaneLenclud@231
   149
                AttributeObjectProperty attribute = attributes[0];
StephaneLenclud@231
   150
Stephane@243
   151
                //Check that we support this type of property
StephaneLenclud@231
   152
                if (!IsPropertyTypeSupported(pi))
StephaneLenclud@231
   153
                {
StephaneLenclud@231
   154
                    continue;
StephaneLenclud@231
   155
                }
StephaneLenclud@231
   156
Stephane@243
   157
                //Now fetch our property value
StephaneLenclud@236
   158
                GetPropertyValueFromControl(iTableLayoutPanel.Controls[ctrlIndex+1], pi, aObject); //+1 otherwise we get the label
StephaneLenclud@231
   159
StephaneLenclud@231
   160
                ctrlIndex+=2; //Jump over the label too
StephaneLenclud@231
   161
            }
StephaneLenclud@231
   162
        }
StephaneLenclud@231
   163
StephaneLenclud@231
   164
        /// <summary>
StephaneLenclud@231
   165
        /// Extend this function to support reading new types of properties.
StephaneLenclud@231
   166
        /// </summary>
StephaneLenclud@236
   167
        /// <param name="aObject"></param>
StephaneLenclud@236
   168
        private void GetPropertyValueFromControl(Control aControl, PropertyInfo aInfo, T aObject)
StephaneLenclud@231
   169
        {
StephaneLenclud@231
   170
            if (aInfo.PropertyType == typeof(int))
StephaneLenclud@231
   171
            {
StephaneLenclud@231
   172
                NumericUpDown ctrl=(NumericUpDown)aControl;
StephaneLenclud@236
   173
                aInfo.SetValue(aObject,(int)ctrl.Value);
StephaneLenclud@231
   174
            }
StephaneLenclud@231
   175
            else if (aInfo.PropertyType.IsEnum)
StephaneLenclud@231
   176
            {
StephaneLenclud@231
   177
                // Instantiate our enum
StephaneLenclud@231
   178
                object enumValue= Activator.CreateInstance(aInfo.PropertyType);
StephaneLenclud@231
   179
                // Parse our enum from combo box
StephaneLenclud@231
   180
                enumValue = Enum.Parse(aInfo.PropertyType,((ComboBox)aControl).SelectedItem.ToString());
StephaneLenclud@231
   181
                //enumValue = ((ComboBox)aControl).SelectedValue;
StephaneLenclud@231
   182
                // Set enum value
StephaneLenclud@236
   183
                aInfo.SetValue(aObject, enumValue);
StephaneLenclud@231
   184
            }
StephaneLenclud@231
   185
            else if (aInfo.PropertyType == typeof(bool))
StephaneLenclud@231
   186
            {
StephaneLenclud@231
   187
                CheckBox ctrl = (CheckBox)aControl;
StephaneLenclud@236
   188
                aInfo.SetValue(aObject, ctrl.Checked);
StephaneLenclud@231
   189
            }
StephaneLenclud@231
   190
            else if (aInfo.PropertyType == typeof(string))
StephaneLenclud@231
   191
            {
StephaneLenclud@231
   192
                TextBox ctrl = (TextBox)aControl;
StephaneLenclud@236
   193
                aInfo.SetValue(aObject, ctrl.Text);
StephaneLenclud@231
   194
            }
StephaneLenclud@238
   195
            else if (aInfo.PropertyType == typeof(PropertyFile))
StephaneLenclud@238
   196
            {
StephaneLenclud@238
   197
                Button ctrl = (Button)aControl;
StephaneLenclud@238
   198
                PropertyFile value = new PropertyFile {FullPath=ctrl.Text};
StephaneLenclud@238
   199
                aInfo.SetValue(aObject, value);
StephaneLenclud@238
   200
            }
Stephane@243
   201
            else if (aInfo.PropertyType == typeof(PropertyComboBox))
Stephane@243
   202
            {
Stephane@243
   203
                ComboBox ctrl = (ComboBox)aControl;
Stephane@243
   204
                string currentItem = ctrl.SelectedItem.ToString();
StephaneLenclud@244
   205
                PropertyComboBox value = (PropertyComboBox)aInfo.GetValue(aObject);
StephaneLenclud@244
   206
                value.CurrentItem = currentItem;
StephaneLenclud@244
   207
                //Not strictly needed but makes sure the set method is called
StephaneLenclud@244
   208
                aInfo.SetValue(aObject, value);                
Stephane@243
   209
            }
StephaneLenclud@250
   210
            else if (aInfo.PropertyType == typeof(PropertyButton))
StephaneLenclud@250
   211
            {
StephaneLenclud@250
   212
                Button ctrl = (Button)aControl;
StephaneLenclud@250
   213
                PropertyButton value = new PropertyButton { Text = ctrl.Text };
StephaneLenclud@250
   214
                aInfo.SetValue(aObject, value);
StephaneLenclud@250
   215
            }
Stephane@243
   216
StephaneLenclud@231
   217
            //TODO: add support for other types here
StephaneLenclud@231
   218
        }
StephaneLenclud@231
   219
StephaneLenclud@236
   220
StephaneLenclud@231
   221
        /// <summary>
StephaneLenclud@236
   222
        /// Create a control for the given property.
StephaneLenclud@231
   223
        /// </summary>
StephaneLenclud@231
   224
        /// <param name="aInfo"></param>
StephaneLenclud@236
   225
        /// <param name="aAttribute"></param>
StephaneLenclud@236
   226
        /// <param name="aObject"></param>
StephaneLenclud@236
   227
        /// <returns></returns>
StephaneLenclud@236
   228
        private Control CreateControlForProperty(PropertyInfo aInfo, AttributeObjectProperty aAttribute, T aObject)
StephaneLenclud@231
   229
        {
StephaneLenclud@231
   230
            if (aInfo.PropertyType == typeof(int))
StephaneLenclud@231
   231
            {
StephaneLenclud@231
   232
                //Integer properties are using numeric editor
StephaneLenclud@231
   233
                NumericUpDown ctrl = new NumericUpDown();
StephaneLenclud@231
   234
                ctrl.AutoSize = true;
StephaneLenclud@231
   235
                ctrl.Minimum = Int32.Parse(aAttribute.Minimum);
StephaneLenclud@231
   236
                ctrl.Maximum = Int32.Parse(aAttribute.Maximum);
StephaneLenclud@231
   237
                ctrl.Increment = Int32.Parse(aAttribute.Increment);
StephaneLenclud@236
   238
                ctrl.Value = (int)aInfo.GetValue(aObject);
StephaneLenclud@247
   239
                // Hook-in change notification after setting the value 
StephaneLenclud@247
   240
                ctrl.ValueChanged += ControlValueChanged;
StephaneLenclud@231
   241
                return ctrl;
StephaneLenclud@231
   242
            }
StephaneLenclud@231
   243
            else if (aInfo.PropertyType.IsEnum)
StephaneLenclud@231
   244
            {
StephaneLenclud@231
   245
                //Enum properties are using combo box
StephaneLenclud@231
   246
                ComboBox ctrl = new ComboBox();
Stephane@243
   247
                ctrl.AutoSize = true;
Stephane@243
   248
                ctrl.Sorted = true;
StephaneLenclud@231
   249
                ctrl.DropDownStyle = ComboBoxStyle.DropDownList;
StephaneLenclud@231
   250
                //Data source is fine but it gives us duplicate entries for duplicated enum values
StephaneLenclud@231
   251
                //ctrl.DataSource = Enum.GetValues(aInfo.PropertyType);
StephaneLenclud@231
   252
StephaneLenclud@231
   253
                //Therefore we need to explicitly create our items
Stephane@243
   254
                Size cbSize = new Size(0, 0);
StephaneLenclud@231
   255
                foreach (string name in aInfo.PropertyType.GetEnumNames())
StephaneLenclud@231
   256
                {
StephaneLenclud@231
   257
                    ctrl.Items.Add(name.ToString());
StephaneLenclud@231
   258
                    Graphics g = this.CreateGraphics();
StephaneLenclud@231
   259
                    //Since combobox autosize would not work we need to get measure text ourselves
Stephane@243
   260
                    SizeF size = g.MeasureString(name.ToString(), ctrl.Font);
Stephane@243
   261
                    cbSize.Width = Math.Max(cbSize.Width, (int)size.Width);
StephaneLenclud@231
   262
                    cbSize.Height = Math.Max(cbSize.Height, (int)size.Height);
StephaneLenclud@231
   263
                }
StephaneLenclud@231
   264
StephaneLenclud@231
   265
                //Make sure our combobox is large enough
StephaneLenclud@231
   266
                ctrl.MinimumSize = cbSize;
StephaneLenclud@231
   267
StephaneLenclud@231
   268
                // Instantiate our enum
StephaneLenclud@231
   269
                object enumValue = Activator.CreateInstance(aInfo.PropertyType);
StephaneLenclud@236
   270
                enumValue = aInfo.GetValue(aObject);
StephaneLenclud@231
   271
                //Set the current item
StephaneLenclud@231
   272
                ctrl.SelectedItem = enumValue.ToString();
StephaneLenclud@247
   273
                // Hook-in change notification after setting the value 
StephaneLenclud@247
   274
                ctrl.SelectedIndexChanged += ControlValueChanged;
StephaneLenclud@231
   275
StephaneLenclud@231
   276
                return ctrl;
StephaneLenclud@231
   277
            }
StephaneLenclud@231
   278
            else if (aInfo.PropertyType == typeof(bool))
StephaneLenclud@231
   279
            {
StephaneLenclud@231
   280
                CheckBox ctrl = new CheckBox();
StephaneLenclud@231
   281
                ctrl.AutoSize = true;
StephaneLenclud@231
   282
                ctrl.Text = aAttribute.Description;
Stephane@243
   283
                ctrl.Checked = (bool)aInfo.GetValue(aObject);
StephaneLenclud@247
   284
                // Hook-in change notification after setting the value 
StephaneLenclud@247
   285
                ctrl.CheckedChanged += ControlValueChanged;
StephaneLenclud@231
   286
                return ctrl;
StephaneLenclud@231
   287
            }
StephaneLenclud@231
   288
            else if (aInfo.PropertyType == typeof(string))
StephaneLenclud@231
   289
            {
StephaneLenclud@231
   290
                TextBox ctrl = new TextBox();
StephaneLenclud@231
   291
                ctrl.AutoSize = true;
StephaneLenclud@236
   292
                ctrl.Text = (string)aInfo.GetValue(aObject);
StephaneLenclud@247
   293
                // Hook-in change notification after setting the value 
StephaneLenclud@247
   294
                ctrl.TextChanged += ControlValueChanged;
StephaneLenclud@231
   295
                return ctrl;
StephaneLenclud@231
   296
            }
StephaneLenclud@238
   297
            else if (aInfo.PropertyType == typeof(PropertyFile))
StephaneLenclud@238
   298
            {
StephaneLenclud@238
   299
                // We have a file property
StephaneLenclud@238
   300
                // Create a button that will trigger the open file dialog to select our file.
StephaneLenclud@238
   301
                Button ctrl = new Button();
StephaneLenclud@238
   302
                ctrl.AutoSize = true;
StephaneLenclud@238
   303
                ctrl.Text = ((PropertyFile)aInfo.GetValue(aObject)).FullPath;
StephaneLenclud@238
   304
                // Add lambda expression to Click event
StephaneLenclud@238
   305
                ctrl.Click += (sender, e) =>
StephaneLenclud@238
   306
                {
StephaneLenclud@238
   307
                    // Create open file dialog
StephaneLenclud@238
   308
                    OpenFileDialog ofd = new OpenFileDialog();
StephaneLenclud@238
   309
                    ofd.RestoreDirectory = true;
StephaneLenclud@238
   310
                    // Use file filter specified by our property
StephaneLenclud@238
   311
                    ofd.Filter = aAttribute.Filter;
StephaneLenclud@238
   312
                    // Show our dialog
StephaneLenclud@238
   313
                    if (DlgBox.ShowDialog(ofd) == DialogResult.OK)
StephaneLenclud@238
   314
                    {
StephaneLenclud@238
   315
                        // Fetch selected file name
StephaneLenclud@238
   316
                        ctrl.Text = ofd.FileName;
StephaneLenclud@238
   317
                    }
StephaneLenclud@238
   318
                };
StephaneLenclud@238
   319
StephaneLenclud@247
   320
                // Hook-in change notification after setting the value 
StephaneLenclud@247
   321
                ctrl.TextChanged += ControlValueChanged;
StephaneLenclud@238
   322
                return ctrl;
StephaneLenclud@238
   323
            }
Stephane@243
   324
            else if (aInfo.PropertyType == typeof(PropertyComboBox))
Stephane@243
   325
            {
Stephane@243
   326
                //ComboBox property
Stephane@243
   327
                ComboBox ctrl = new ComboBox();
Stephane@243
   328
                ctrl.AutoSize = true;
Stephane@243
   329
                ctrl.Sorted = true;
Stephane@243
   330
                ctrl.DropDownStyle = ComboBoxStyle.DropDownList;
Stephane@243
   331
                //Data source is such a pain to set the current item
Stephane@243
   332
                //ctrl.DataSource = ((PropertyComboBox)aInfo.GetValue(aObject)).Items;                
Stephane@243
   333
Stephane@243
   334
                PropertyComboBox pcb = ((PropertyComboBox)aInfo.GetValue(aObject));
Stephane@243
   335
                foreach (string item in pcb.Items)
Stephane@243
   336
                {
Stephane@243
   337
                    ctrl.Items.Add(item);
Stephane@243
   338
                }
Stephane@243
   339
Stephane@243
   340
                ctrl.SelectedItem = ((PropertyComboBox)aInfo.GetValue(aObject)).CurrentItem;
Stephane@243
   341
                //
Stephane@243
   342
                return ctrl;
Stephane@243
   343
            }
StephaneLenclud@250
   344
            else if (aInfo.PropertyType == typeof(PropertyButton))
StephaneLenclud@250
   345
            {
StephaneLenclud@250
   346
                // We have a button property
StephaneLenclud@250
   347
                // Create a button that will trigger the custom action.
StephaneLenclud@250
   348
                Button ctrl = new Button();
StephaneLenclud@250
   349
                ctrl.AutoSize = true;
StephaneLenclud@250
   350
                ctrl.Text = ((PropertyButton)aInfo.GetValue(aObject)).Text;
StephaneLenclud@250
   351
                // Hook in click event
StephaneLenclud@250
   352
                ctrl.Click += ((PropertyButton)aInfo.GetValue(aObject)).ClickEventHandler;
StephaneLenclud@250
   353
                // Hook-in change notification after setting the value 
StephaneLenclud@250
   354
                ctrl.TextChanged += ControlValueChanged;
StephaneLenclud@250
   355
                return ctrl;
StephaneLenclud@250
   356
            }
StephaneLenclud@250
   357
StephaneLenclud@231
   358
            //TODO: add support for other control type here
StephaneLenclud@231
   359
            return null;
StephaneLenclud@231
   360
        }
StephaneLenclud@231
   361
StephaneLenclud@231
   362
        /// <summary>
StephaneLenclud@231
   363
        /// Don't forget to extend that one and adding types
StephaneLenclud@231
   364
        /// </summary>
StephaneLenclud@231
   365
        /// <returns></returns>
StephaneLenclud@231
   366
        private bool IsPropertyTypeSupported(PropertyInfo aInfo)
StephaneLenclud@231
   367
        {
StephaneLenclud@231
   368
            if (aInfo.PropertyType == typeof(int))
StephaneLenclud@231
   369
            {
StephaneLenclud@231
   370
                return true;
StephaneLenclud@231
   371
            }
StephaneLenclud@231
   372
            else if (aInfo.PropertyType.IsEnum)
StephaneLenclud@231
   373
            {
StephaneLenclud@231
   374
                return true;
StephaneLenclud@231
   375
            }
StephaneLenclud@231
   376
            else if (aInfo.PropertyType == typeof(bool))
StephaneLenclud@231
   377
            {
StephaneLenclud@231
   378
                return true;
StephaneLenclud@231
   379
            }
StephaneLenclud@231
   380
            else if (aInfo.PropertyType == typeof(string))
StephaneLenclud@231
   381
            {
StephaneLenclud@231
   382
                return true;
StephaneLenclud@231
   383
            }
StephaneLenclud@238
   384
            else if (aInfo.PropertyType == typeof(PropertyFile))
StephaneLenclud@238
   385
            {
StephaneLenclud@238
   386
                return true;
StephaneLenclud@238
   387
            }
Stephane@243
   388
            else if (aInfo.PropertyType == typeof(PropertyComboBox))
Stephane@243
   389
            {
Stephane@243
   390
                return true;
Stephane@243
   391
            }
StephaneLenclud@250
   392
            else if (aInfo.PropertyType == typeof(PropertyButton))
StephaneLenclud@250
   393
            {
StephaneLenclud@250
   394
                return true;
StephaneLenclud@250
   395
            }
Stephane@243
   396
StephaneLenclud@231
   397
            //TODO: add support for other type here
StephaneLenclud@231
   398
StephaneLenclud@231
   399
            return false;
StephaneLenclud@231
   400
        }
StephaneLenclud@231
   401
StephaneLenclud@231
   402
        /// <summary>
StephaneLenclud@231
   403
        /// Update our table layout.
StephaneLenclud@246
   404
        /// Will instantiated every field control as defined by our object.
StephaneLenclud@231
   405
        /// </summary>
StephaneLenclud@231
   406
        /// <param name="aLayout"></param>
StephaneLenclud@247
   407
        private void UpdateControls()
StephaneLenclud@231
   408
        {
StephaneLenclud@247
   409
StephaneLenclud@231
   410
            toolTip.RemoveAll();
StephaneLenclud@231
   411
            //Debug.Print("UpdateTableLayoutPanel")
StephaneLenclud@231
   412
            //First clean our current panel
StephaneLenclud@231
   413
            iTableLayoutPanel.Controls.Clear();
StephaneLenclud@231
   414
            iTableLayoutPanel.RowStyles.Clear();
StephaneLenclud@231
   415
            iTableLayoutPanel.ColumnStyles.Clear();
StephaneLenclud@231
   416
            iTableLayoutPanel.RowCount = 0;
StephaneLenclud@231
   417
StephaneLenclud@231
   418
            //We always want two columns: one for label and one for the field
StephaneLenclud@231
   419
            iTableLayoutPanel.ColumnCount = 2;
StephaneLenclud@231
   420
            iTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
StephaneLenclud@231
   421
            iTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
StephaneLenclud@231
   422
StephaneLenclud@231
   423
StephaneLenclud@247
   424
            if (Object == null)
StephaneLenclud@231
   425
            {
StephaneLenclud@231
   426
                //Just drop it
StephaneLenclud@231
   427
                return;
StephaneLenclud@231
   428
            }
StephaneLenclud@246
   429
StephaneLenclud@247
   430
            UpdateStaticControls();
StephaneLenclud@247
   431
StephaneLenclud@236
   432
            //IEnumerable<PropertyInfo> properties = aObject.GetType().GetProperties().Where(
StephaneLenclud@231
   433
            //    prop => Attribute.IsDefined(prop, typeof(AttributeObjectProperty)));
StephaneLenclud@231
   434
StephaneLenclud@246
   435
            //TODO: Do this whenever a field changes
StephaneLenclud@247
   436
            iLabelBrief.Text = Object.Brief();
StephaneLenclud@246
   437
StephaneLenclud@231
   438
StephaneLenclud@247
   439
            foreach (PropertyInfo pi in Object.GetType().GetProperties())
StephaneLenclud@231
   440
            {
StephaneLenclud@231
   441
                AttributeObjectProperty[] attributes = ((AttributeObjectProperty[])pi.GetCustomAttributes(typeof(AttributeObjectProperty), true));
StephaneLenclud@231
   442
                if (attributes.Length != 1)
StephaneLenclud@231
   443
                {
StephaneLenclud@231
   444
                    continue;
StephaneLenclud@231
   445
                }
StephaneLenclud@231
   446
StephaneLenclud@231
   447
                AttributeObjectProperty attribute = attributes[0];
StephaneLenclud@231
   448
StephaneLenclud@231
   449
                //Before anything we need to check if that kind of property is supported by our UI
StephaneLenclud@231
   450
                //Create the editor
StephaneLenclud@247
   451
                Control ctrl = CreateControlForProperty(pi, attribute, Object);
StephaneLenclud@231
   452
                if (ctrl == null)
StephaneLenclud@231
   453
                {
StephaneLenclud@231
   454
                    //Property type not supported
StephaneLenclud@231
   455
                    continue;
StephaneLenclud@231
   456
                }
StephaneLenclud@231
   457
StephaneLenclud@231
   458
                //Add a new row
StephaneLenclud@231
   459
                iTableLayoutPanel.RowCount++;
StephaneLenclud@231
   460
                iTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
StephaneLenclud@231
   461
                //Create the label
StephaneLenclud@231
   462
                Label label = new Label();
StephaneLenclud@231
   463
                label.AutoSize = true;
StephaneLenclud@231
   464
                label.Dock = DockStyle.Fill;
StephaneLenclud@231
   465
                label.TextAlign = ContentAlignment.MiddleCenter;
StephaneLenclud@231
   466
                label.Text = attribute.Name;
StephaneLenclud@231
   467
                toolTip.SetToolTip(label, attribute.Description);
StephaneLenclud@231
   468
                iTableLayoutPanel.Controls.Add(label, 0, iTableLayoutPanel.RowCount-1);
StephaneLenclud@231
   469
StephaneLenclud@231
   470
                //Add our editor to our form
StephaneLenclud@231
   471
                iTableLayoutPanel.Controls.Add(ctrl, 1, iTableLayoutPanel.RowCount - 1);
StephaneLenclud@231
   472
                //Add tooltip to editor too
StephaneLenclud@231
   473
                toolTip.SetToolTip(ctrl, attribute.Description);
StephaneLenclud@231
   474
StephaneLenclud@246
   475
            }
StephaneLenclud@231
   476
StephaneLenclud@246
   477
            //Entrer object edit mode
StephaneLenclud@246
   478
            Object.CurrentState = SharpLib.Ear.Object.State.Edit;
StephaneLenclud@246
   479
            Object.PropertyChanged += PropertyChangedEventHandlerThreadSafe;
StephaneLenclud@246
   480
        }
StephaneLenclud@246
   481
StephaneLenclud@247
   482
        /// <summary>
StephaneLenclud@247
   483
        /// 
StephaneLenclud@247
   484
        /// </summary>
StephaneLenclud@247
   485
        /// <param name="sender"></param>
StephaneLenclud@247
   486
        /// <param name="e"></param>
StephaneLenclud@246
   487
        void PropertyChangedEventHandlerThreadSafe(object sender, PropertyChangedEventArgs e)
StephaneLenclud@246
   488
        {
StephaneLenclud@246
   489
            if (this.InvokeRequired)
StephaneLenclud@246
   490
            {
StephaneLenclud@246
   491
                //Not in the proper thread, invoke ourselves
StephaneLenclud@246
   492
                PropertyChangedEventHandler d = new PropertyChangedEventHandler(PropertyChangedEventHandlerThreadSafe);
StephaneLenclud@246
   493
                this.Invoke(d, new object[] { sender, e });
StephaneLenclud@246
   494
            }
StephaneLenclud@246
   495
            else
StephaneLenclud@246
   496
            {
StephaneLenclud@247
   497
                // We could test the name of the property that has changed as follow
StephaneLenclud@247
   498
                // It's currently not needed though
StephaneLenclud@247
   499
                //if (e.PropertyName == "Brief")
StephaneLenclud@246
   500
StephaneLenclud@247
   501
                // Our object has changed behind our back.
StephaneLenclud@247
   502
                // That's currently only the case for HID events that are listening for inputs.
StephaneLenclud@250
   503
                if (Object is EventHid)
StephaneLenclud@250
   504
                {
StephaneLenclud@250
   505
                    //HID can't do full control updates for some reason
StephaneLenclud@250
   506
                    //We are getting spammed with HID events after a few clicks
StephaneLenclud@250
   507
                    //We need to investigate, HID bug?
StephaneLenclud@250
   508
                    UpdateStaticControls();
StephaneLenclud@250
   509
                }
StephaneLenclud@250
   510
                else
StephaneLenclud@250
   511
                {
StephaneLenclud@250
   512
                    UpdateControls();
StephaneLenclud@250
   513
                }
StephaneLenclud@246
   514
            }
StephaneLenclud@231
   515
        }
StephaneLenclud@231
   516
StephaneLenclud@231
   517
        private void buttonTest_Click(object sender, EventArgs e)
StephaneLenclud@231
   518
        {
StephaneLenclud@231
   519
            FetchPropertiesValue(Object);
StephaneLenclud@231
   520
StephaneLenclud@231
   521
            //If our object has a test method with no parameters just run it then
StephaneLenclud@231
   522
            MethodInfo info = Object.GetType().GetMethod("Test");
StephaneLenclud@231
   523
            if ( info != null && info.GetParameters().Length==0)
StephaneLenclud@231
   524
            {
StephaneLenclud@231
   525
                info.Invoke(Object,null);
StephaneLenclud@231
   526
            }
StephaneLenclud@231
   527
StephaneLenclud@231
   528
        }
StephaneLenclud@247
   529
StephaneLenclud@247
   530
StephaneLenclud@247
   531
        /// <summary>
StephaneLenclud@247
   532
        /// 
StephaneLenclud@247
   533
        /// </summary>
StephaneLenclud@247
   534
        /// <param name="sender"></param>
StephaneLenclud@247
   535
        /// <param name="e"></param>
StephaneLenclud@247
   536
        private void ControlValueChanged(object sender, EventArgs e)
StephaneLenclud@247
   537
        {
StephaneLenclud@247
   538
            UpdateObject();
StephaneLenclud@247
   539
        }
StephaneLenclud@247
   540
StephaneLenclud@247
   541
        /// <summary>
StephaneLenclud@247
   542
        /// 
StephaneLenclud@247
   543
        /// </summary>
StephaneLenclud@247
   544
        private void UpdateObject()
StephaneLenclud@247
   545
        {
StephaneLenclud@247
   546
            // Update our object with the content of our controls
StephaneLenclud@247
   547
            FetchPropertiesValue(Object);
StephaneLenclud@247
   548
StephaneLenclud@247
   549
            UpdateStaticControls();
StephaneLenclud@247
   550
            //
StephaneLenclud@247
   551
            //PerformLayout();
StephaneLenclud@247
   552
        }
StephaneLenclud@247
   553
StephaneLenclud@247
   554
        /// <summary>
StephaneLenclud@247
   555
        /// 
StephaneLenclud@247
   556
        /// </summary>
StephaneLenclud@247
   557
        private void UpdateStaticControls()
StephaneLenclud@247
   558
        {
StephaneLenclud@247
   559
            // Update OK and test button status
StephaneLenclud@247
   560
            iButtonOk.Enabled = Object.IsValid();
StephaneLenclud@247
   561
            iButtonTest.Enabled = iButtonOk.Enabled;
StephaneLenclud@247
   562
StephaneLenclud@247
   563
            // Update brief title
StephaneLenclud@247
   564
            iLabelBrief.Text = Object.Brief();
StephaneLenclud@247
   565
StephaneLenclud@247
   566
            // Update object description
StephaneLenclud@260
   567
            iLabelDescription.Text = Object.AttributeDescription;
StephaneLenclud@247
   568
        }
StephaneLenclud@247
   569
StephaneLenclud@247
   570
        /// <summary>
StephaneLenclud@247
   571
        /// 
StephaneLenclud@247
   572
        /// </summary>
StephaneLenclud@247
   573
        /// <param name="sender"></param>
StephaneLenclud@247
   574
        /// <param name="e"></param>
StephaneLenclud@247
   575
        private void iComboBoxObjectType_KeyPress(object sender, KeyPressEventArgs e)
StephaneLenclud@247
   576
        {
StephaneLenclud@247
   577
            //Special case for HID events
StephaneLenclud@247
   578
            if (Object is EventHid)
StephaneLenclud@247
   579
            {
StephaneLenclud@247
   580
                //Disable handling of key input as we are using key input for changing our event
StephaneLenclud@247
   581
                e.Handled = true;
StephaneLenclud@247
   582
            }
StephaneLenclud@247
   583
        }
StephaneLenclud@260
   584
StephaneLenclud@260
   585
        private void iComboBoxObjectType_Enter(object sender, EventArgs e)
StephaneLenclud@260
   586
        {
StephaneLenclud@260
   587
            //Only edit HID event when our type combo box has the focus
StephaneLenclud@260
   588
            // TODO: That's an ugly workaround, fix that somehow. Maybe by only doing HID scan when a button property has the focus
StephaneLenclud@260
   589
            if (Object is EventHid)
StephaneLenclud@260
   590
            {
StephaneLenclud@260
   591
                Object.CurrentState = SharpLib.Ear.Object.State.Edit;
StephaneLenclud@260
   592
            }
StephaneLenclud@260
   593
        }
StephaneLenclud@260
   594
StephaneLenclud@260
   595
        private void iComboBoxObjectType_Leave(object sender, EventArgs e)
StephaneLenclud@260
   596
        {
StephaneLenclud@260
   597
            //Only edit HID event when our type combo box has the focus
StephaneLenclud@260
   598
            // TODO: That's an ugly workaround, fix that somehow. Maybe by only doing HID scan when a button property has the focus
StephaneLenclud@260
   599
            if (Object is EventHid)
StephaneLenclud@260
   600
            {
StephaneLenclud@260
   601
                Object.CurrentState = SharpLib.Ear.Object.State.Rest;
StephaneLenclud@260
   602
            }
StephaneLenclud@260
   603
        }
StephaneLenclud@231
   604
    }
StephaneLenclud@231
   605
}