private Grid CreateCollectionEditor(Record record, Type itemType) { var value = record.GetValue(_object); 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 Label { VerticalAlignment = VerticalAlignment.Center, }; UpdateLabelCount(label, items.Count); subGrid.Widgets.Add(label); var button = new ImageTextButton { 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(); }; subGrid.Widgets.Add(button); return(subGrid); }
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; } }