public PropertyControl(PropertiesView view, ObsProperty property, ObsData setting)
        {
            SuspendLayout();
            AutoSize = true;
            Margin   = new Padding(0, 1, 0, 1);
            Size     = new Size(600, 25);
            ResumeLayout(false);

            this.view = view;

            DoubleBuffered = true;
            Padding        = new Padding(2);

            ObsPropertyType type     = property.Type;
            bool            addLabel = true;
            List <Control>  controls = new List <Control>();

            switch (type)
            {
            case ObsPropertyType.Bool:
            {
                addLabel = false;
                AddBool(property, setting, controls);
                break;
            }

            case ObsPropertyType.Int:
            case ObsPropertyType.Float:
            {
                AddNumeric(property, setting, controls);
                break;
            }

            case ObsPropertyType.Text:
            {
                AddText(property, setting, controls);
                break;
            }

            case ObsPropertyType.Path:
            {
                AddPath(property, setting, controls);
                break;
            }

            case ObsPropertyType.List:
            {
                AddList(property, setting, controls);
                break;
            }

            case ObsPropertyType.Color:
            {
                AddColor(property, setting, controls);
                break;
            }

            case ObsPropertyType.Button:
            {
                addLabel = false;
                AddButton(property, setting, controls);
                break;
            }

            case ObsPropertyType.Font:
            {
                AddFont(property, setting, controls);
                break;
            }

            case ObsPropertyType.EditableList:
            {
                addLabel = false;
                AddEditableList(property, setting, controls);
                break;
            }

            default:
            {
                throw new Exception(String.Format("Error, unimplemented property type {0} for property {1}", type, property.Description));
            }
            }

            Label nameLabel = new Label
            {
                Text        = addLabel ? property.Description : "",
                TextAlign   = ContentAlignment.MiddleRight,
                MinimumSize = new Size(170, 0),
                AutoSize    = true,
                Dock        = DockStyle.Left
            };

            controls.Insert(0, nameLabel);

            foreach (Control control in controls)
            {
                WinFormsHelper.DoubleBufferControl(control);

                int     margin    = 0;
                Padding oldmargin = control.Margin;
                oldmargin.Top    = margin;
                oldmargin.Bottom = margin;
                control.Margin   = oldmargin;
            }

            SuspendLayout();
            Controls.AddRange(controls.ToArray());
            ResumeLayout();
        }
        private void AddNumeric(ObsProperty property, ObsData setting, List <Control> controls)
        {
            ObsPropertyType type = property.Type;
            string          name = property.Name;

            NumericUpDown numeric = new NumericUpDown
            {
                Width         = 300,
                DecimalPlaces = 0
            };

            if (type == ObsPropertyType.Int)
            {
                int  intMin   = property.IntMin;
                int  intMax   = property.IntMax;
                long intValue = setting.GetInt(name);
                intValue = Math.Max(Math.Min(intValue, intMax), intMin);

                numeric.Minimum   = intMin;
                numeric.Maximum   = intMax;
                numeric.Increment = property.IntStep;
                numeric.Value     = intValue;

                numeric.ValueChanged += (sender, args) =>
                {
                    setting.SetInt(name, (int)numeric.Value);
                    view.PropertyChanged(property);
                };
            }
            else if (type == ObsPropertyType.Float)
            {
                double floatMin   = property.FloatMin;
                double floatMax   = property.FloatMax;
                double floatValue = setting.GetDouble(name);
                floatValue = Math.Max(Math.Min(floatValue, floatMax), floatMin);

                numeric.DecimalPlaces = 2;
                numeric.Minimum       = (decimal)floatMin;
                numeric.Maximum       = (decimal)floatMax;
                numeric.Increment     = (decimal)property.FloatStep;
                numeric.Value         = (decimal)floatValue;

                numeric.ValueChanged += (sender, args) =>
                {
                    setting.SetDouble(name, (double)numeric.Value);
                    view.PropertyChanged(property);
                };
            }

            if (property.IntType == ObsNumberType.Slider || property.FloatType == ObsNumberType.Slider)
            {
                numeric.Width  = 75;
                numeric.Height = 23;

                const int multiplier = 1000;
                var       trackbar   = new TrackBar
                {
                    AutoSize    = false,
                    Width       = 300,
                    Height      = 23,
                    TickStyle   = TickStyle.None,
                    Minimum     = (int)(numeric.Minimum * multiplier),
                    Maximum     = (int)(numeric.Maximum * multiplier),
                    SmallChange = (int)(numeric.Increment * multiplier),
                    LargeChange = (int)(numeric.Increment * multiplier),
                    Value       = (int)(numeric.Value * multiplier)
                };
                trackbar.ValueChanged += (sender, args) => numeric.Value = (decimal)trackbar.Value / multiplier;
                numeric.ValueChanged  += (sender, args) => trackbar.Value = (int)(numeric.Value * multiplier);
                controls.Add(trackbar);
            }
            controls.Add(numeric);
        }