コード例 #1
0
ファイル: PropertyGrid.cs プロジェクト: kopffarben/Myra
        private void FillSubGrid(ref int y, IReadOnlyList <Record> records)
        {
            for (var i = 0; i < records.Count; ++i)
            {
                var record = records[i];

                var hasSetter = record.HasSetter;
                if (_parentProperty != null && !_parentProperty.HasSetter)
                {
                    hasSetter = false;
                }

                var    value       = record.GetValue(_object);
                Widget valueWidget = null;

                var oldY = y;

                var propertyType = record.Type;

                Proportion rowProportion;
                if (record.ItemsProvider != null)
                {
                    var values = record.ItemsProvider.Items;

                    var cb = new ComboBox();
                    foreach (var v in values)
                    {
                        cb.Items.Add(new ListItem(v.ToString(), null, v));
                    }


                    cb.SelectedIndex = Array.IndexOf(values, value);
                    if (hasSetter)
                    {
                        cb.SelectedIndexChanged += (sender, args) =>
                        {
                            var item = cb.SelectedItem != null ? values[cb.SelectedIndex] : null;
                            record.SetValue(_object, item);
                            FireChanged(propertyType.Name);
                        };
                    }
                    else
                    {
                        cb.Enabled = false;
                    }

                    valueWidget = cb;
                }
                else if (propertyType == typeof(bool))
                {
                    var isChecked = (bool)value;
                    var cb        = new CheckBox
                    {
                        IsPressed = isChecked
                    };

                    if (hasSetter)
                    {
                        cb.Click += (sender, args) =>
                        {
                            record.SetValue(_object, cb.IsPressed);
                            FireChanged(propertyType.Name);
                        };
                    }
                    else
                    {
                        cb.Enabled = false;
                    }

                    valueWidget = cb;
                }
                else if (propertyType == typeof(Color) || propertyType == typeof(Color?))
                {
                    var subGrid = new Grid
                    {
                        ColumnSpacing       = 8,
                        HorizontalAlignment = HorizontalAlignment.Stretch
                    };

                    var isColor = propertyType == typeof(Color);

                    subGrid.ColumnsProportions.Add(new Proportion());
                    subGrid.ColumnsProportions.Add(new Proportion(ProportionType.Fill));

                    var color = Color.Transparent;
                    if (isColor)
                    {
                        color = (Color)value;
                    }
                    else if (value != null)
                    {
                        color = ((Color?)value).Value;
                    }

                    var image = new Image
                    {
                        Renderable        = DefaultAssets.WhiteRegion,
                        VerticalAlignment = VerticalAlignment.Center,
                        Width             = 32,
                        Height            = 16,
                        Color             = color
                    };

                    subGrid.Widgets.Add(image);

                    var button = new Button
                    {
                        Text = "Change...",
                        ContentHorizontalAlignment = HorizontalAlignment.Center,
                        Tag = value,
                        HorizontalAlignment = HorizontalAlignment.Stretch,
                        GridColumn          = 1
                    };

                    subGrid.Widgets.Add(button);

                    if (hasSetter)
                    {
                        button.Click += (sender, args) =>
                        {
                            var dlg = new ColorPickerDialog()
                            {
                                Color = image.Color
                            };

                            dlg.Closed += (s, a) =>
                            {
                                if (!dlg.Result)
                                {
                                    return;
                                }

                                image.Color = dlg.Color;
                                record.SetValue(_object, dlg.Color);

                                FireChanged(propertyType.Name);
                            };

                            dlg.ShowModal(Desktop);
                        };
                    }
                    else
                    {
                        button.Enabled = false;
                    }

                    valueWidget = subGrid;
                }
                else if (propertyType.IsAssignableFrom(typeof(IRenderable)))
                {
                }
                else if (propertyType.IsEnum)
                {
                    var values = Enum.GetValues(propertyType);

                    var cb = new ComboBox();
                    foreach (var v in values)
                    {
                        cb.Items.Add(new ListItem(v.ToString(), null, v));
                    }

                    cb.SelectedIndex = Array.IndexOf(values, value);

                    if (hasSetter)
                    {
                        cb.SelectedIndexChanged += (sender, args) =>
                        {
                            if (cb.SelectedIndex != -1)
                            {
                                record.SetValue(_object, cb.SelectedIndex);
                                FireChanged(propertyType.Name);
                            }
                        };
                    }
                    else
                    {
                        cb.Enabled = false;
                    }

                    valueWidget = cb;
                }
                else if (propertyType.IsNumericType() ||
                         (propertyType.IsNullablePrimitive() && propertyType.GetNullableType().IsNumericType()))
                {
                    var numericType = propertyType;
                    if (propertyType.IsNullablePrimitive())
                    {
                        numericType = propertyType.GetNullableType();
                    }

                    var spinButton = new SpinButton
                    {
                        Integer  = numericType.IsNumericInteger(),
                        Nullable = propertyType.IsNullablePrimitive(),
                        Value    = value != null ? (float)Convert.ChangeType(value, typeof(float)) : default(float?)
                    };

                    if (hasSetter)
                    {
                        spinButton.ValueChanged += (sender, args) =>
                        {
                            try
                            {
                                object result;

                                if (spinButton.Value != null)
                                {
                                    result = Convert.ChangeType(spinButton.Value.Value, numericType);
                                }
                                else
                                {
                                    result = null;
                                }

                                record.SetValue(_object, result);

                                if (record.Type.IsValueType)
                                {
                                    var tg = this;
                                    var pg = tg._parentGrid;
                                    while (pg != null && tg._parentProperty != null)
                                    {
                                        tg._parentProperty.SetValue(pg._object, tg._object);

                                        if (!tg._parentProperty.Type.IsValueType)
                                        {
                                            break;
                                        }

                                        tg = pg;
                                        pg = tg._parentGrid;
                                    }
                                }

                                FireChanged(record.Name);
                            }
                            catch (InvalidCastException)
                            {
                                // TODO: Rework this ugly type conversion solution
                            }
                            catch (Exception ex)
                            {
                                spinButton.Value = args.OldValue;
                                var dialog = Dialog.CreateMessageBox("Error", ex.ToString());
                                dialog.ShowModal(Desktop);
                            }
                        };
                    }
                    else
                    {
                        spinButton.Enabled = false;
                    }

                    valueWidget = spinButton;
                }
                else if (propertyType == typeof(string) || propertyType.IsPrimitive || propertyType.IsNullablePrimitive())
                {
                    var tf = new TextField
                    {
                        Text = value != null?value.ToString() : string.Empty
                    };

                    if (hasSetter)
                    {
                        tf.TextChanged += (sender, args) =>
                        {
                            try
                            {
                                object result;

                                if (propertyType.IsNullablePrimitive())
                                {
                                    if (string.IsNullOrEmpty(tf.Text))
                                    {
                                        result = null;
                                    }
                                    else
                                    {
                                        result = Convert.ChangeType(tf.Text, record.Type.GetNullableType());
                                    }
                                }
                                else
                                {
                                    result = Convert.ChangeType(tf.Text, record.Type);
                                }

                                record.SetValue(_object, result);

                                if (record.Type.IsValueType)
                                {
                                    var tg = this;
                                    var pg = tg._parentGrid;
                                    while (pg != null && tg._parentProperty != null)
                                    {
                                        tg._parentProperty.SetValue(pg._object, tg._object);

                                        if (!tg._parentProperty.Type.IsValueType)
                                        {
                                            break;
                                        }

                                        tg = pg;
                                        pg = tg._parentGrid;
                                    }
                                }

                                FireChanged(record.Name);
                            }
                            catch (Exception)
                            {
                                // TODO: Rework this ugly type conversion solution
                            }
                        };
                    }
                    else
                    {
                        tf.Enabled = false;
                    }

                    valueWidget = tf;
                }
                else if (typeof(IList).IsAssignableFrom(propertyType))
                {
                    var it = propertyType.FindGenericType(typeof(ICollection <>));
                    if (it != null)
                    {
                        var itemType = it.GenericTypeArguments[0];
                        if (value != null)
                        {
                            var items = (IList)value;

                            var subGrid = new Grid
                            {
                                ColumnSpacing       = 8,
                                HorizontalAlignment = HorizontalAlignment.Stretch
                            };

                            subGrid.ColumnsProportions.Add(new Proportion());
                            subGrid.ColumnsProportions.Add(new Proportion(ProportionType.Fill));

                            var label = new TextBlock
                            {
                                VerticalAlignment = VerticalAlignment.Center,
                            };
                            UpdateLabelCount(label, items.Count);

                            subGrid.Widgets.Add(label);

                            var button = new Button
                            {
                                Text = "Change...",
                                ContentHorizontalAlignment = HorizontalAlignment.Center,
                                Tag = value,
                                HorizontalAlignment = HorizontalAlignment.Stretch,
                                GridColumn          = 1
                            };

                            button.Click += (sender, args) =>
                            {
                                var collectionEditor = new CollectionEditor(items, itemType);

                                var dialog = Dialog.CreateMessageBox("Edit", collectionEditor);

                                dialog.ButtonOk.Click += (o, eventArgs) =>
                                {
                                    collectionEditor.SaveChanges();
                                    UpdateLabelCount(label, items.Count);
                                };

                                dialog.ShowModal(Desktop);
                            };

                            subGrid.Widgets.Add(button);
                            valueWidget = subGrid;
                        }
                    }
                }
                else if (!(value is SpriteFont) && !(value is IRenderable))
                {
                    // Subgrid
                    if (value != null)
                    {
                        var subGrid = new SubGrid(this, value, record.Name, DefaultCategoryName, record)
                        {
                            GridColumnSpan = 2,
                            GridRow        = y
                        };

                        InternalChild.Widgets.Add(subGrid);

                        rowProportion = new Proportion(ProportionType.Auto);
                        InternalChild.RowsProportions.Add(rowProportion);
                        ++y;

                        continue;
                    }

                    var tb = new TextBlock();
                    tb.ApplyTextBlockStyle(PropertyGridStyle.LabelStyle);
                    tb.Text = "null";

                    valueWidget = tb;
                }

                if (valueWidget == null)
                {
                    continue;
                }

                var nameLabel = new TextBlock
                {
                    Text = record.Name,
                    VerticalAlignment = VerticalAlignment.Center,
                    GridColumn        = 0,
                    GridRow           = oldY
                };

                InternalChild.Widgets.Add(nameLabel);

                valueWidget.GridColumn          = 1;
                valueWidget.GridRow             = oldY;
                valueWidget.HorizontalAlignment = HorizontalAlignment.Stretch;
                valueWidget.VerticalAlignment   = VerticalAlignment.Top;

                InternalChild.Widgets.Add(valueWidget);

                rowProportion = new Proportion(ProportionType.Auto);
                InternalChild.RowsProportions.Add(rowProportion);
                ++y;
            }
        }